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

Jeremy Huddleston jeremyhu at freedesktop.org
Sat Apr 5 14:16:31 PDT 2014


 Xext/Makefile.am                             |    4 
 Xext/sync.c                                  |    7 
 Xi/Makefile.am                               |    5 
 Xi/exevents.c                                |    5 
 Xi/xipassivegrab.c                           |    4 
 composite/compext.c                          |   13 
 composite/compinit.c                         |   24 
 composite/compint.h                          |    7 
 composite/compositeext.h                     |    4 
 composite/compwindow.c                       |   18 
 config/Makefile.am                           |    2 
 config/config.c                              |  105 +++-
 config/hal.c                                 |   16 
 config/non-seat0.conf.multi-seat             |   18 
 config/udev.c                                |   74 +--
 configure.ac                                 |  115 +++-
 dix/devices.c                                |    3 
 dix/events.c                                 |   46 -
 dix/gc.c                                     |    8 
 dix/globals.c                                |    3 
 dix/main.c                                   |    4 
 dri3/dri3.h                                  |    6 
 dri3/dri3_request.c                          |   38 -
 dri3/dri3_screen.c                           |    2 
 fb/Makefile.am                               |    3 
 fb/fbblt.c                                   |   60 +-
 fb/fbpict.c                                  |    4 
 fb/fbpict.h                                  |   15 
 glamor/Makefile.am                           |   22 
 glamor/glamor.c                              |  197 +++++--
 glamor/glamor.h                              |  115 ++--
 glamor/glamor_addtraps.c                     |    2 
 glamor/glamor_context.h                      |   56 ++
 glamor/glamor_copyarea.c                     |  155 ++----
 glamor/glamor_copyplane.c                    |   15 
 glamor/glamor_core.c                         |  244 ++++-----
 glamor/glamor_egl.c                          |  395 ++++++++--------
 glamor/glamor_egl_stubs.c                    |   16 
 glamor/glamor_eglmodule.c                    |    3 
 glamor/glamor_fbo.c                          |   58 --
 glamor/glamor_fill.c                         |  152 +++---
 glamor/glamor_fillspans.c                    |  108 ----
 glamor/glamor_font.c                         |  186 +++++++
 glamor/glamor_font.h                         |   49 +
 glamor/glamor_getimage.c                     |    2 
 glamor/glamor_getspans.c                     |   92 ---
 glamor/glamor_gl_dispatch.c                  |  118 ----
 glamor/glamor_gl_dispatch.h                  |  128 -----
 glamor/glamor_glext.h                        |   63 --
 glamor/glamor_glx.c                          |   76 +++
 glamor/glamor_glyphblt.c                     |  284 +++++++++--
 glamor/glamor_glyphs.c                       |   31 -
 glamor/glamor_gradient.c                     |  660 +++++++++-----------------
 glamor/glamor_largepixmap.c                  |   10 
 glamor/glamor_picture.c                      |    7 
 glamor/glamor_pixmap.c                       |  582 +++++++++++++++++------
 glamor/glamor_points.c                       |  144 +++++
 glamor/glamor_polyfillrect.c                 |  124 -----
 glamor/glamor_polylines.c                    |   28 -
 glamor/glamor_polyops.c                      |   82 ---
 glamor/glamor_priv.h                         |  257 ++++++----
 glamor/glamor_program.c                      |  386 +++++++++++++++
 glamor/glamor_program.h                      |   94 +++
 glamor/glamor_putimage.c                     |  203 --------
 glamor/glamor_rects.c                        |  189 +++++++
 glamor/glamor_render.c                       |  416 +++++-----------
 glamor/glamor_segment.c                      |   39 +
 glamor/glamor_setspans.c                     |  112 ----
 glamor/glamor_spans.c                        |  438 +++++++++++++++++
 glamor/glamor_text.c                         |  526 +++++++++++++++++++++
 glamor/glamor_tile.c                         |  101 +---
 glamor/glamor_transfer.c                     |  264 ++++++++++
 glamor/glamor_transfer.h                     |   55 ++
 glamor/glamor_transform.c                    |  215 ++++++++
 glamor/glamor_transform.h                    |   87 +++
 glamor/glamor_trapezoid.c                    |  299 +++++-------
 glamor/glamor_triangles.c                    |   15 
 glamor/glamor_utils.h                        |  408 +---------------
 glamor/glamor_vbo.c                          |  186 +++++++
 glamor/glamor_xv.c                           |  172 ++----
 glx/glxdricommon.c                           |    2 
 hw/Makefile.am                               |    9 
 hw/dmx/Makefile.am                           |    1 
 hw/dmx/dmxinit.c                             |    4 
 hw/kdrive/ephyr/Makefile.am                  |   20 
 hw/kdrive/ephyr/ephyr.c                      |   45 +
 hw/kdrive/ephyr/ephyr.h                      |   14 
 hw/kdrive/ephyr/ephyr_glamor_glx.c           |  346 ++++++++++++++
 hw/kdrive/ephyr/ephyr_glamor_glx.h           |   83 +++
 hw/kdrive/ephyr/ephyrinit.c                  |   19 
 hw/kdrive/ephyr/hostx.c                      |  141 +++++
 hw/kdrive/src/Makefile.am                    |    5 
 hw/kdrive/src/kxv.c                          |   27 -
 hw/kdrive/src/kxv.h                          |   36 -
 hw/vfb/InitOutput.c                          |    5 
 hw/vfb/Makefile.am                           |   11 
 hw/xfree86/.gitignore                        |    1 
 hw/xfree86/Makefile.am                       |   23 
 hw/xfree86/Xorg.sh.in                        |   11 
 hw/xfree86/common/xf86Events.c               |   43 +
 hw/xfree86/common/xf86Extensions.c           |    5 
 hw/xfree86/common/xf86Globals.c              |    2 
 hw/xfree86/common/xf86Helper.c               |   31 +
 hw/xfree86/common/xf86Init.c                 |   19 
 hw/xfree86/common/xf86Module.h               |    4 
 hw/xfree86/common/xf86Privstr.h              |    4 
 hw/xfree86/common/xf86Xinput.c               |   87 +++
 hw/xfree86/common/xf86Xinput.h               |    8 
 hw/xfree86/common/xf86platformBus.c          |   88 ++-
 hw/xfree86/common/xf86platformBus.h          |   18 
 hw/xfree86/common/xf86str.h                  |    3 
 hw/xfree86/dixmods/Makefile.am               |    4 
 hw/xfree86/dixmods/glxmodule.c               |    8 
 hw/xfree86/doc/ddxDesign.xml                 |    4 
 hw/xfree86/glamor_egl/Makefile.am            |   43 +
 hw/xfree86/man/Makefile.am                   |    5 
 hw/xfree86/man/Xorg.man                      |    6 
 hw/xfree86/man/Xorg.wrap.man                 |   67 ++
 hw/xfree86/man/Xwrapper.config.man           |    1 
 hw/xfree86/man/xorg.conf.man                 |    6 
 hw/xfree86/modes/xf86Crtc.h                  |    4 
 hw/xfree86/modes/xf86Cursors.c               |   35 -
 hw/xfree86/os-support/linux/Makefile.am      |    6 
 hw/xfree86/os-support/linux/lnx_init.c       |   25 -
 hw/xfree86/os-support/linux/lnx_platform.c   |   42 +
 hw/xfree86/os-support/linux/systemd-logind.c |  605 ++++++++++++++++++++++++
 hw/xfree86/os-support/shared/posix_tty.c     |    6 
 hw/xfree86/parser/DRI.c                      |    1 
 hw/xfree86/parser/Extensions.c               |    1 
 hw/xfree86/ramdac/IBM.c                      |    6 
 hw/xfree86/ramdac/TI.c                       |    3 
 hw/xfree86/ramdac/xf86Cursor.c               |   11 
 hw/xfree86/ramdac/xf86Cursor.h               |    4 
 hw/xfree86/ramdac/xf86CursorPriv.h           |    2 
 hw/xfree86/ramdac/xf86HWCurs.c               |   15 
 hw/xfree86/xorg-wrapper.c                    |  231 +++++++++
 hw/xnest/Makefile.am                         |    9 
 hw/xquartz/Makefile.am                       |    1 
 hw/xquartz/quartz.c                          |    5 
 hw/xwayland/.gitignore                       |    3 
 hw/xwayland/Makefile.am                      |   30 +
 hw/xwayland/xwayland-cursor.c                |  193 +++++++
 hw/xwayland/xwayland-cvt.c                   |  304 ++++++++++++
 hw/xwayland/xwayland-input.c                 |  666 +++++++++++++++++++++++++++
 hw/xwayland/xwayland-output.c                |  226 +++++++++
 hw/xwayland/xwayland-shm.c                   |  292 +++++++++++
 hw/xwayland/xwayland.c                       |  652 ++++++++++++++++++++++++++
 hw/xwayland/xwayland.h                       |  164 ++++++
 hw/xwin/InitInput.c                          |    9 
 hw/xwin/InitOutput.c                         |   17 
 hw/xwin/Makefile.am                          |    9 
 hw/xwin/glx/gen_gl_wrappers.py               |   45 -
 hw/xwin/glx/indirect.c                       |    2 
 hw/xwin/man/XWin.man                         |    6 
 hw/xwin/win.h                                |    9 
 hw/xwin/winallpriv.c                         |    4 
 hw/xwin/winauth.c                            |    4 
 hw/xwin/winclipboardinit.c                   |    2 
 hw/xwin/winclipboardxevents.c                |    5 
 hw/xwin/wincursor.c                          |   10 
 hw/xwin/windialogs.c                         |   56 --
 hw/xwin/winglobals.c                         |    1 
 hw/xwin/winglobals.h                         |    1 
 hw/xwin/winkeybd.c                           |    2 
 hw/xwin/winmonitors.h                        |    2 
 hw/xwin/winmsgwindow.c                       |    4 
 hw/xwin/winmultiwindowicons.c                |   26 -
 hw/xwin/winmultiwindowwm.c                   |  140 ++++-
 hw/xwin/winmultiwindowwndproc.c              |   24 
 hw/xwin/winnativegdi.c                       |    3 
 hw/xwin/winprefslex.l                        |    3 
 hw/xwin/winprefsyacc.y                       |   25 -
 hw/xwin/winprocarg.c                         |    5 
 hw/xwin/winresource.h                        |    3 
 hw/xwin/winshadgdi.c                         |    6 
 hw/xwin/winwin32rootless.c                   |    8 
 hw/xwin/winwindow.c                          |    2 
 hw/xwin/winwindowswm.c                       |    4 
 hw/xwin/winwndproc.c                         |    6 
 include/Makefile.am                          |    1 
 include/dix-config.h.in                      |   12 
 include/extension.h                          |    3 
 include/hotplug.h                            |   33 +
 include/input.h                              |    7 
 include/opaque.h                             |    2 
 include/os.h                                 |    6 
 include/scrnintstr.h                         |    7 
 include/systemd-logind.h                     |   45 +
 include/xkbsrv.h                             |   18 
 include/xorg-config.h.in                     |   14 
 include/xwin-config.h.in                     |    6 
 manpages.am                                  |    1 
 mi/mi.h                                      |    4 
 mi/mibitblt.c                                |    2 
 mi/miinitext.c                               |   46 -
 mi/miscrinit.c                               |    1 
 mi/miwindow.c                                |   66 ++
 miext/sync/misyncstr.h                       |    1 
 os/connection.c                              |   51 +-
 os/log.c                                     |    4 
 os/utils.c                                   |    6 
 randr/rrcrtc.c                               |   14 
 test/Makefile.am                             |    9 
 test/hashtabletest.c                         |    2 
 test/input.c                                 |    4 
 test/os.c                                    |    4 
 test/signal-logging.c                        |    4 
 xkb/ddxLoad.c                                |  244 +++++++--
 xkb/xkb.c                                    |   16 
 xkb/xkbAccessX.c                             |    2 
 xkb/xkbActions.c                             |  102 ++--
 xkb/xkbInit.c                                |   42 +
 xkb/xkbUtils.c                               |   43 +
 213 files changed, 11138 insertions(+), 4207 deletions(-)

New commits:
commit 901fbfbbbd71c0d82080957f8ba09eebbc786f2b
Author: Michael Thayer <michael.thayer at oracle.com>
Date:   Mon Mar 31 11:21:42 2014 +0200

    Add a return value to load_cursor_argb() to allow it to report failure
    
    load_cursor_argb() may need to be able to fail and have the server fall back
    to a software cursor in at least the following circumstances.
    1) The hardware can only support some ARGB cursors and this does not just
    depend on cursor size.
    2) Virtual hardware may not wish to pass through a cursor to the host at a
    particular time but may wish to accept the same cursor at another time.
    This patch adds a return value to the API and makes the server do the
    software fall-back on failure.
    
    Signed-off-by: Michael Thayer <michael.thayer at oracle.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index e8c24f2..62ac95d 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -80,7 +80,7 @@ typedef enum {
  * mask is 0xFFFF0000.
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
-#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(16, 0)
+#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(17, 0)
 #define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(8, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index c127d78..5407deb 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -186,13 +186,13 @@ typedef struct _xf86CrtcFuncs {
     /**
      * Load monochrome image
      */
-    void
+    Bool
      (*load_cursor_image) (xf86CrtcPtr crtc, CARD8 *image);
 
     /**
      * Load ARGB image
      */
-    void
+    Bool
      (*load_cursor_argb) (xf86CrtcPtr crtc, CARD32 *image);
 
     /**
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 2b0db34..10ef6f6 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -211,7 +211,7 @@ set_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
 /*
  * Load a two color cursor into a driver that supports only ARGB cursors
  */
-static void
+static Bool
 xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src)
 {
     ScrnInfoPtr scrn = crtc->scrn;
@@ -244,7 +244,7 @@ xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src)
                 bits = 0;
             cursor_image[y * cursor_info->MaxWidth + x] = bits;
         }
-    crtc->funcs->load_cursor_argb(crtc, cursor_image);
+    return crtc->funcs->load_cursor_argb(crtc, cursor_image);
 }
 
 /*
@@ -415,7 +415,7 @@ xf86_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
 /*
  * Load a two-color cursor into a crtc, performing rotation as needed
  */
-static void
+static Bool
 xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src)
 {
     ScrnInfoPtr scrn = crtc->scrn;
@@ -450,13 +450,13 @@ xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src)
                     set_bit(cursor_image, cursor_info, x, y, TRUE);
             }
     }
-    crtc->funcs->load_cursor_image(crtc, cursor_image);
+    return crtc->funcs->load_cursor_image(crtc, cursor_image);
 }
 
 /*
  * Load a cursor image into all active CRTCs
  */
-static void
+static Bool
 xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
 {
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -466,12 +466,17 @@ xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
         xf86CrtcPtr crtc = xf86_config->crtc[c];
 
         if (crtc->enabled) {
-            if (crtc->funcs->load_cursor_image)
-                xf86_crtc_load_cursor_image(crtc, src);
-            else if (crtc->funcs->load_cursor_argb)
-                xf86_crtc_convert_cursor_to_argb(crtc, src);
+            if (crtc->funcs->load_cursor_image) {
+                if (!xf86_crtc_load_cursor_image(crtc, src))
+                    return FALSE;
+            } else if (crtc->funcs->load_cursor_argb) {
+                if (!xf86_crtc_convert_cursor_to_argb(crtc, src))
+                    return FALSE;
+            } else
+                return FALSE;
         }
     }
+    return TRUE;
 }
 
 static Bool
@@ -516,7 +521,7 @@ xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
     return TRUE;
 }
 
-static void
+static Bool
 xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor)
 {
     ScrnInfoPtr scrn = crtc->scrn;
@@ -544,10 +549,10 @@ xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor)
             cursor_image[y * image_width + x] = bits;
         }
 
-    crtc->funcs->load_cursor_argb(crtc, cursor_image);
+    return crtc->funcs->load_cursor_argb(crtc, cursor_image);
 }
 
-static void
+static Bool
 xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor)
 {
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -557,8 +562,10 @@ xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor)
         xf86CrtcPtr crtc = xf86_config->crtc[c];
 
         if (crtc->enabled)
-            xf86_crtc_load_cursor_argb(crtc, cursor);
+            if (!xf86_crtc_load_cursor_argb(crtc, cursor))
+                return FALSE;
     }
+    return TRUE;
 }
 
 Bool
@@ -608,6 +615,8 @@ xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags)
  * Called when anything on the screen is reconfigured.
  *
  * Reloads cursor images as needed, then adjusts cursor positions
+ * @note We assume that all hardware cursors to be loaded have already been
+ *       found to be usable by the hardware.
  */
 
 void
diff --git a/hw/xfree86/ramdac/IBM.c b/hw/xfree86/ramdac/IBM.c
index bc71623..872d3d4 100644
--- a/hw/xfree86/ramdac/IBM.c
+++ b/hw/xfree86/ramdac/IBM.c
@@ -570,7 +570,7 @@ IBMramdac640SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
     (*ramdacPtr->WriteData) (pScrn, bg);
 }
 
-static void
+static Bool
 IBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
 {
     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
@@ -582,9 +582,10 @@ IBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
      */
     for (i = 0; i < 1024; i++)
         (*ramdacPtr->WriteDAC) (pScrn, IBMRGB_curs_array + i, 0x00, (*src++));
+    return TRUE;
 }
 
-static void
+static Bool
 IBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
 {
     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
@@ -596,6 +597,7 @@ IBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
      */
     for (i = 0; i < 1024; i++)
         (*ramdacPtr->WriteDAC) (pScrn, RGB640_CURS_WRITE + i, 0x00, (*src++));
+    return TRUE;
 }
 
 static Bool
diff --git a/hw/xfree86/ramdac/TI.c b/hw/xfree86/ramdac/TI.c
index 393b774..7d4e0d7 100644
--- a/hw/xfree86/ramdac/TI.c
+++ b/hw/xfree86/ramdac/TI.c
@@ -642,7 +642,7 @@ TIramdacSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
     (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_COLOR, 0, (fg & 0x000000ff));
 }
 
-static void
+static Bool
 TIramdacLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
 {
     RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
@@ -657,6 +657,7 @@ TIramdacLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
         /* NOT_DONE: might need a delay here */
         (*ramdacPtr->WriteDAC) (pScrn, TIDAC_CURS_RAM_DATA, 0, *(src++));
     }
+    return TRUE;
 }
 
 static Bool
diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 860704e..fac6822 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -352,12 +352,13 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
                 (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen,
                                                        NullCursor, x, y);
 
-            xf86SetCursor(pScreen, cursor, x, y);
-            ScreenPriv->SWCursor = FALSE;
-            ScreenPriv->isUp = TRUE;
+            if (xf86SetCursor(pScreen, cursor, x, y)) {
+                ScreenPriv->SWCursor = FALSE;
+                ScreenPriv->isUp = TRUE;
 
-            miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse);
-            return;
+                miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse);
+                return;
+            }
         }
 
         miPointerSetWaitForUpdate(pScreen, TRUE);
diff --git a/hw/xfree86/ramdac/xf86Cursor.h b/hw/xfree86/ramdac/xf86Cursor.h
index 5658e7b..1ecbdcd 100644
--- a/hw/xfree86/ramdac/xf86Cursor.h
+++ b/hw/xfree86/ramdac/xf86Cursor.h
@@ -12,7 +12,7 @@ typedef struct _xf86CursorInfoRec {
     int MaxHeight;
     void (*SetCursorColors) (ScrnInfoPtr pScrn, int bg, int fg);
     void (*SetCursorPosition) (ScrnInfoPtr pScrn, int x, int y);
-    void (*LoadCursorImage) (ScrnInfoPtr pScrn, unsigned char *bits);
+    Bool (*LoadCursorImage) (ScrnInfoPtr pScrn, unsigned char *bits);
     void (*HideCursor) (ScrnInfoPtr pScrn);
     void (*ShowCursor) (ScrnInfoPtr pScrn);
     unsigned char *(*RealizeCursor) (struct _xf86CursorInfoRec *, CursorPtr);
@@ -20,7 +20,7 @@ typedef struct _xf86CursorInfoRec {
 
 #ifdef ARGB_CURSOR
     Bool (*UseHWCursorARGB) (ScreenPtr, CursorPtr);
-    void (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr);
+    Bool (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr);
 #endif
 
 } xf86CursorInfoRec, *xf86CursorInfoPtr;
diff --git a/hw/xfree86/ramdac/xf86CursorPriv.h b/hw/xfree86/ramdac/xf86CursorPriv.h
index a5d2aab..f34c1c7 100644
--- a/hw/xfree86/ramdac/xf86CursorPriv.h
+++ b/hw/xfree86/ramdac/xf86CursorPriv.h
@@ -37,7 +37,7 @@ typedef struct {
     void *transparentData;
 } xf86CursorScreenRec, *xf86CursorScreenPtr;
 
-void xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y);
+Bool xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y);
 void xf86SetTransparentCursor(ScreenPtr pScreen);
 void xf86MoveCursor(ScreenPtr pScreen, int x, int y);
 void xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed);
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index 3b69698..0b5caa2 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -119,7 +119,7 @@ xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
     return TRUE;
 }
 
-void
+Bool
 xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
 {
     xf86CursorScreenPtr ScreenPriv =
@@ -130,7 +130,7 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
 
     if (pCurs == NullCursor) {
         (*infoPtr->HideCursor) (infoPtr->pScrn);
-        return;
+        return TRUE;
     }
 
     bits =
@@ -152,18 +152,21 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
         (*infoPtr->HideCursor) (infoPtr->pScrn);
 
 #ifdef ARGB_CURSOR
-    if (pCurs->bits->argb && infoPtr->LoadCursorARGB)
-        (*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs);
-    else
+    if (pCurs->bits->argb && infoPtr->LoadCursorARGB) {
+        if (!(*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs))
+            return FALSE;
+    } else
 #endif
     if (bits)
-        (*infoPtr->LoadCursorImage) (infoPtr->pScrn, bits);
+        if (!(*infoPtr->LoadCursorImage) (infoPtr->pScrn, bits))
+            return FALSE;
 
     xf86RecolorCursor(pScreen, pCurs, 1);
 
     (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
 
     (*infoPtr->ShowCursor) (infoPtr->pScrn);
+    return TRUE;
 }
 
 void
commit 62ab4102260fd3342a0e5ae3a4f77b430af64f4e
Author: Michael Thayer <michael.thayer at oracle.com>
Date:   Mon Mar 31 11:19:16 2014 +0200

    Set a flag property on the root window to say if the X server VT is active
    
    An X11 client may need to know whether the X server virtual terminal is
    currently the active one.  This change adds a root window property which
    provides that information.  Intended interface user: the VirtualBox Guest
    Additions.
    
    Signed-off-by: Michael Thayer <michael.thayer at oracle.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 06af739..35a673d 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -56,6 +56,7 @@
 #include <X11/X.h>
 #include <X11/Xpoll.h>
 #include <X11/Xproto.h>
+#include <X11/Xatom.h>
 #include "misc.h"
 #include "compiler.h"
 #include "xf86.h"
@@ -431,6 +432,29 @@ xf86EnableInputDeviceForVTSwitch(InputInfoPtr pInfo)
     pInfo->flags &= ~XI86_DEVICE_DISABLED;
 }
 
+/*
+ * xf86UpdateHasVTProperty --
+ *    Update a flag property on the root window to say whether the server VT
+ *    is currently the active one as some clients need to know this.
+ */
+static void
+xf86UpdateHasVTProperty(Bool hasVT)
+{
+    Atom property_name;
+    int32_t value = hasVT ? 1 : 0;
+    int i;
+
+    property_name = MakeAtom(HAS_VT_ATOM_NAME, sizeof(HAS_VT_ATOM_NAME) - 1,
+                             FALSE);
+    if (property_name == BAD_RESOURCE)
+        FatalError("Failed to retrieve \"HAS_VT\" atom\n");
+    for (i = 0; i < xf86NumScreens; i++) {
+        ChangeWindowProperty(xf86ScrnToScreen(xf86Screens[i])->root,
+                             property_name, XA_INTEGER, 32,
+                             PropModeReplace, 1, &value, TRUE);
+    }
+}
+
 void
 xf86VTLeave(void)
 {
@@ -490,6 +514,8 @@ xf86VTLeave(void)
     if (xorgHWAccess)
         xf86DisableIO();
 
+    xf86UpdateHasVTProperty(FALSE);
+
     return;
 
 switch_failed:
@@ -574,6 +600,8 @@ xf86VTEnter(void)
     xf86platformVTProbe();
 #endif
 
+    xf86UpdateHasVTProperty(TRUE);
+
     OsReleaseSIGIO();
 }
 
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 4579ff5..5a45004 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -387,6 +387,11 @@ InstallSignalHandlers(void)
     }
 }
 
+/* The memory storing the initial value of the XFree86_has_VT root window
+ * property.  This has to remain available until server start-up, so we just
+ * use a global. */
+static CARD32 HasVTValue = 1;
+
 /*
  * InitOutput --
  *	Initialize screenInfo for all actually accessible framebuffers.
@@ -731,7 +736,9 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
         if (xf86Info.vtno >= 0) {
 #define VT_ATOM_NAME         "XFree86_VT"
             Atom VTAtom = -1;
+            Atom HasVTAtom = -1;
             CARD32 *VT = NULL;
+            CARD32 *HasVT = &HasVTValue;
             int ret;
 
             /* This memory needs to stay available until the screen has been
@@ -744,6 +751,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
             *VT = xf86Info.vtno;
 
             VTAtom = MakeAtom(VT_ATOM_NAME, sizeof(VT_ATOM_NAME) - 1, TRUE);
+            HasVTAtom = MakeAtom(HAS_VT_ATOM_NAME,
+                                 sizeof(HAS_VT_ATOM_NAME) - 1, TRUE);
 
             for (i = 0, ret = Success; i < xf86NumScreens && ret == Success;
                  i++) {
@@ -751,9 +760,14 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
                     xf86RegisterRootWindowProperty(xf86Screens[i]->scrnIndex,
                                                    VTAtom, XA_INTEGER, 32, 1,
                                                    VT);
+                if (ret == Success)
+                    ret = xf86RegisterRootWindowProperty(xf86Screens[i]
+                                                             ->scrnIndex,
+                                                         HasVTAtom, XA_INTEGER,
+                                                         32, 1, HasVT);
                 if (ret != Success)
                     xf86DrvMsg(xf86Screens[i]->scrnIndex, X_WARNING,
-                               "Failed to register VT property\n");
+                               "Failed to register VT properties\n");
             }
         }
 
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
index f7a9c9f..410ef17 100644
--- a/hw/xfree86/common/xf86Privstr.h
+++ b/hw/xfree86/common/xf86Privstr.h
@@ -163,4 +163,8 @@ typedef struct _RootWinProp {
 #define WSCONS		  32
 #endif
 
+/* Root window property to tell clients whether our VT is currently active.
+ * Name chosen to match the "XFree86_VT" property. */
+#define HAS_VT_ATOM_NAME "XFree86_has_VT"
+
 #endif                          /* _XF86PRIVSTR_H */
commit b851ca968b7cce6d1a6438c05d3d5c8832249704
Author: Daniel Stone <daniels at collabora.com>
Date:   Thu Apr 3 18:22:50 2014 +0100

    Add pScreen->NameWindowPixmap hook
    
    This hook allows drivers to be notified when a pixmap gains a new ID.
    
    (ABI break.)
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/composite/compext.c b/composite/compext.c
index a945f72..cadedbd 100644
--- a/composite/compext.c
+++ b/composite/compext.c
@@ -239,6 +239,7 @@ ProcCompositeNameWindowPixmap(ClientPtr client)
     WindowPtr pWin;
     CompWindowPtr cw;
     PixmapPtr pPixmap;
+    ScreenPtr pScreen;
     int rc;
 
     REQUEST(xCompositeNameWindowPixmapReq);
@@ -246,6 +247,8 @@ ProcCompositeNameWindowPixmap(ClientPtr client)
     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
 
+    pScreen = pWin->drawable.pScreen;
+
     if (!pWin->viewable)
         return BadMatch;
 
@@ -255,7 +258,7 @@ ProcCompositeNameWindowPixmap(ClientPtr client)
     if (!cw)
         return BadMatch;
 
-    pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+    pPixmap = (*pScreen->GetWindowPixmap) (pWin);
     if (!pPixmap)
         return BadMatch;
 
@@ -270,6 +273,14 @@ ProcCompositeNameWindowPixmap(ClientPtr client)
     if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pPixmap))
         return BadAlloc;
 
+    if (pScreen->NameWindowPixmap) {
+        rc = pScreen->NameWindowPixmap(pWin, pPixmap, stuff->pixmap);
+        if (rc != Success) {
+            FreeResource(stuff->pixmap, RT_NONE);
+            return rc;
+        }
+    }
+
     return Success;
 }
 
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 5197c79..6acdadd 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -356,6 +356,8 @@ typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
 typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen,
                                        SpritePtr pSprite, int x, int y);
 
+typedef int (*NameWindowPixmapProcPtr)(WindowPtr, PixmapPtr, CARD32);
+
 typedef struct _Screen {
     int myNum;                  /* index of this instance in Screens[] */
     ATOM id;
@@ -466,6 +468,7 @@ typedef struct _Screen {
     SetWindowPixmapProcPtr SetWindowPixmap;
     GetScreenPixmapProcPtr GetScreenPixmap;
     SetScreenPixmapProcPtr SetScreenPixmap;
+    NameWindowPixmapProcPtr NameWindowPixmap;
 
     PixmapPtr pScratchPixmap;   /* scratch pixmap "pool" */
 
commit b4d0bec22c15930abf13a7fb9d684208ccd56b1d
Merge: 3c34dd3 6e539d8
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Apr 3 15:35:01 2014 -0700

    Merge remote-tracking branch 'krh/xwayland-for-keithp'

commit 6e539d8817f738289dc2dea13d0720116287ab9d
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Tue Mar 11 16:11:39 2014 -0700

    Xwayland DDX
    
    Started out as an Xorg module to be used from Xorg drivers to let
    Xorg run under a wayland server.  The idea was to be able to reuse the
    2D acceleration from the Xorg driver.  Now with glamor being credible,
    a better plan is to just make Xwayland its own DDX, similar to Xwin
    and Xquartz.  This is a much better fit, as much of the code in the
    original approach had to hack around Xorg doing Xorg things like take
    over the VT, probe input devices and read config files.  Another big win
    is that Xwayland dosn't need to be setuid root.
    
    The Xwayland support for DRI3, Glamor and render nodes was done by
    Axel Davy <axel.davy at ens.fr>, who also did a lot of work on the rebase
    to the Xwayland DDX.
    
    Contributions from:
    
      Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>
      Corentin Chary <corentin.chary at gmail.com>
      Daniel Stone <daniel at fooishbar.org>
      Kristian Høgsberg <krh at bitplanet.net>
      Robert Bragg <robert at linux.intel.com>
      Scott Moreau <oreaus at gmail.com>
      Tiago Vignatti <tiago.vignatti at intel.com>
      Giovanni Campagna <gcampagn at redhat.com>
      Jonas Ã…dahl <jadahl at gmail.com>
      Ray Strode <rstrode at redhat.com>
      Trevor McCort <tjmccort at gmail.com>
      Rui Matos <tiagomatos at gmail.com>
      Axel Davy <axel.davy at ens.fr>
      Jasper St. Pierre <jstpierre at mecheye.net>
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Axel Davy <axel.davy at ens.fr>

diff --git a/configure.ac b/configure.ac
index f589d6d..6e01b54 100644
--- a/configure.ac
+++ b/configure.ac
@@ -633,6 +633,7 @@ AC_ARG_ENABLE(dmx,    	      AS_HELP_STRING([--enable-dmx], [Build DMX server (d
 AC_ARG_ENABLE(xvfb,    	      AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes])
 AC_ARG_ENABLE(xnest,   	      AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto])
 AC_ARG_ENABLE(xquartz,        AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto])
+AC_ARG_ENABLE(xwayland,       AS_HELP_STRING([--enable-xwayland], [Build Xwayland server (default: auto)]), [XWAYLAND=$enableval], [XWAYLAND=auto])
 AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no])
 AC_ARG_ENABLE(xwin,    	      AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto])
 AC_ARG_ENABLE(glamor,         AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: no)]), [GLAMOR=$enableval], [GLAMOR=no])
@@ -751,6 +752,7 @@ case $host_os in
 			XQUARTZ=yes
 			XVFB=no
 			XNEST=no
+			XWAYLAND=no
 
 			COMPOSITE=no
 			DGA=no
@@ -2432,6 +2434,29 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes])
 AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes])
 AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes])
 
+dnl Xwayland DDX
+
+PKG_CHECK_MODULES(XWAYLANDMODULES, [wayland-client libdrm epoxy], [have_xwayland=yes], [have_xwayland=no])
+AC_MSG_CHECKING([whether to build Xwayland DDX])
+if test "x$XWAYLAND" = xauto; then
+   XWAYLAND="$have_xwayland"
+fi
+AC_MSG_RESULT([$XWAYLAND])
+AM_CONDITIONAL(XWAYLAND, [test "x$XWAYLAND" = xyes])
+
+if test "x$XWAYLAND" = xyes; then
+	if test "x$have_xwayland" = xno; then
+		AC_MSG_ERROR([Xwayland build explicitly requested, but required modules not found.])
+	fi
+
+	XWAYLAND_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
+	XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS"
+	AC_SUBST([XWAYLAND_LIBS])
+	AC_SUBST([XWAYLAND_SYS_LIBS])
+	WAYLAND_SCANNER_RULES(['$(top_srcdir)/hw/xwayland'])
+fi
+
+
 dnl and the rest of these are generic, so they're in config.h
 dnl 
 dnl though, thanks to the passing of some significant amount of time, the
@@ -2574,6 +2599,7 @@ hw/kdrive/fake/Makefile
 hw/kdrive/fbdev/Makefile
 hw/kdrive/linux/Makefile
 hw/kdrive/src/Makefile
+hw/xwayland/Makefile
 test/Makefile
 test/xi2/Makefile
 xserver.ent
diff --git a/hw/Makefile.am b/hw/Makefile.am
index 6c2cc6b..19895dc 100644
--- a/hw/Makefile.am
+++ b/hw/Makefile.am
@@ -26,6 +26,10 @@ if XQUARTZ
 XQUARTZ_SUBDIRS = xquartz
 endif
 
+if XWAYLAND
+XWAYLAND_SUBDIRS = xwayland
+endif
+
 SUBDIRS =			\
 	$(XORG_SUBDIRS)		\
 	$(XWIN_SUBDIRS)		\
@@ -33,9 +37,10 @@ SUBDIRS =			\
 	$(XNEST_SUBDIRS)	\
 	$(DMX_SUBDIRS)		\
 	$(KDRIVE_SUBDIRS)	\
-	$(XQUARTZ_SUBDIRS)
+	$(XQUARTZ_SUBDIRS)	\
+	$(XWAYLAND_SUBDIRS)
 
-DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
+DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
 
 relink:
 	$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore
new file mode 100644
index 0000000..c54ba2d
--- /dev/null
+++ b/hw/xwayland/.gitignore
@@ -0,0 +1,3 @@
+Xwayland
+drm-client-protocol.h
+drm-protocol.c
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
new file mode 100644
index 0000000..36e6127
--- /dev/null
+++ b/hw/xwayland/Makefile.am
@@ -0,0 +1,30 @@
+bin_PROGRAMS = Xwayland
+
+Xwayland_CFLAGS =				\
+	-I$(top_srcdir)/dri3			\
+	-DHAVE_DIX_CONFIG_H			\
+	$(XWAYLANDMODULES_CFLAGS)		\
+	$(DIX_CFLAGS)
+
+Xwayland_SOURCES =				\
+	xwayland.c				\
+	xwayland-input.c			\
+	xwayland-cursor.c			\
+	xwayland-shm.c				\
+	xwayland-output.c			\
+	xwayland-cvt.c				\
+	xwayland.h				\
+	$(top_srcdir)/Xext/dpmsstubs.c		\
+	$(top_srcdir)/Xi/stubs.c		\
+	$(top_srcdir)/mi/miinitext.c
+
+Xwayland_LDADD =				\
+	$(XWAYLAND_LIBS)			\
+	$(XWAYLAND_SYS_LIBS)			\
+	$(XSERVER_SYS_LIBS)
+Xwayland_DEPENDENCIES = $(XWAYLAND_LIBS)
+Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
+
+
+relink:
+	$(AM_V_at)rm -f Xwayland$(EXEEXT) && $(MAKE) Xwayland$(EXEEXT)
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
new file mode 100644
index 0000000..5a9d1fe
--- /dev/null
+++ b/hw/xwayland/xwayland-cursor.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2011 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "xwayland.h"
+
+#include <mipointer.h>
+
+static DevPrivateKeyRec xwl_cursor_private_key;
+
+static void
+expand_source_and_mask(CursorPtr cursor, CARD32 *data)
+{
+    CARD32 *p, d, fg, bg;
+    CursorBitsPtr bits = cursor->bits;
+    int x, y, stride, i, bit;
+
+    p = data;
+    fg = ((cursor->foreRed & 0xff00) << 8) |
+        (cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8);
+    bg = ((cursor->backRed & 0xff00) << 8) |
+        (cursor->backGreen & 0xff00) | (cursor->backGreen >> 8);
+    stride = (bits->width / 8 + 3) & ~3;
+    for (y = 0; y < bits->height; y++)
+        for (x = 0; x < bits->width; x++) {
+            i = y * stride + x / 8;
+            bit = 1 << (x & 7);
+            if (bits->source[i] & bit)
+                d = fg;
+            else
+                d = bg;
+            if (bits->mask[i] & bit)
+                d |= 0xff000000;
+            else
+                d = 0x00000000;
+
+            *p++ = d;
+        }
+}
+
+static Bool
+xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+    PixmapPtr pixmap;
+
+    pixmap = xwl_shm_create_pixmap(screen, cursor->bits->width,
+                                   cursor->bits->height, 32, 0);
+    dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, pixmap);
+
+    return TRUE;
+}
+
+static Bool
+xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
+{
+    PixmapPtr pixmap;
+
+    pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
+
+    return xwl_shm_destroy_pixmap(pixmap);
+}
+
+void
+xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
+{
+    PixmapPtr pixmap;
+    CursorPtr cursor;
+    int stride;
+
+    if (!xwl_seat->wl_pointer)
+        return;
+
+    if (!xwl_seat->x_cursor) {
+        wl_pointer_set_cursor(xwl_seat->wl_pointer,
+                              xwl_seat->pointer_enter_serial, NULL, 0, 0);
+        return;
+    }
+
+    cursor = xwl_seat->x_cursor;
+    pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
+    stride = cursor->bits->width * 4;
+    if (cursor->bits->argb)
+        memcpy(pixmap->devPrivate.ptr,
+               cursor->bits->argb, cursor->bits->height * stride);
+    else
+        expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+
+    wl_pointer_set_cursor(xwl_seat->wl_pointer,
+                          xwl_seat->pointer_enter_serial,
+                          xwl_seat->cursor,
+                          xwl_seat->x_cursor->bits->xhot,
+                          xwl_seat->x_cursor->bits->yhot);
+    wl_surface_attach(xwl_seat->cursor,
+                      xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
+    wl_surface_damage(xwl_seat->cursor, 0, 0,
+                      xwl_seat->x_cursor->bits->width,
+                      xwl_seat->x_cursor->bits->height);
+    wl_surface_commit(xwl_seat->cursor);
+}
+
+static void
+xwl_set_cursor(DeviceIntPtr device,
+               ScreenPtr screen, CursorPtr cursor, int x, int y)
+{
+    struct xwl_seat *xwl_seat;
+
+    xwl_seat = device->public.devicePrivate;
+    if (xwl_seat == NULL)
+        return;
+
+    xwl_seat->x_cursor = cursor;
+    xwl_seat_set_cursor(xwl_seat);
+}
+
+static void
+xwl_move_cursor(DeviceIntPtr device, ScreenPtr screen, int x, int y)
+{
+}
+
+static Bool
+xwl_device_cursor_initialize(DeviceIntPtr device, ScreenPtr screen)
+{
+    return TRUE;
+}
+
+static void
+xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen)
+{
+}
+
+static miPointerSpriteFuncRec xwl_pointer_sprite_funcs = {
+    xwl_realize_cursor,
+    xwl_unrealize_cursor,
+    xwl_set_cursor,
+    xwl_move_cursor,
+    xwl_device_cursor_initialize,
+    xwl_device_cursor_cleanup
+};
+
+static Bool
+xwl_cursor_off_screen(ScreenPtr *ppScreen, int *x, int *y)
+{
+    return FALSE;
+}
+
+static void
+xwl_cross_screen(ScreenPtr pScreen, Bool entering)
+{
+}
+
+static void
+xwl_pointer_warp_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+{
+}
+
+static miPointerScreenFuncRec xwl_pointer_screen_funcs = {
+    xwl_cursor_off_screen,
+    xwl_cross_screen,
+    xwl_pointer_warp_cursor
+};
+
+Bool
+xwl_screen_init_cursor(struct xwl_screen *xwl_screen)
+{
+    if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0))
+        return FALSE;
+
+    return miPointerInitialize(xwl_screen->screen,
+                               &xwl_pointer_sprite_funcs,
+                               &xwl_pointer_screen_funcs, TRUE);
+}
diff --git a/hw/xwayland/xwayland-cvt.c b/hw/xwayland/xwayland-cvt.c
new file mode 100644
index 0000000..3566559
--- /dev/null
+++ b/hw/xwayland/xwayland-cvt.c
@@ -0,0 +1,304 @@
+/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and
+ * changed to generate an RRMode */
+
+/*
+ * Copyright 2005-2006 Luc Verhaegen.
+ *
+ * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ */
+
+/*
+ * The reason for having this function in a file of its own is
+ * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
+ * code is shared directly.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include <randrstr.h>
+#include "xwayland.h"
+
+/*
+ * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
+ *
+ * These calculations are stolen from the CVT calculation spreadsheet written
+ * by Graham Loveridge. He seems to be claiming no copyright and there seems to
+ * be no license attached to this. He apparently just wants to see his name
+ * mentioned.
+ *
+ * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
+ *
+ * Comments and structure corresponds to the comments and structure of the xls.
+ * This should ease importing of future changes to the standard (not very
+ * likely though).
+ *
+ * About margins; i'm sure that they are to be the bit between HDisplay and
+ * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
+ * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
+ * outside sync "margin" for some reason. Since we prefer seeing proper
+ * blanking instead of the overscan colour, and since the Crtc* values will
+ * probably get altered after us, we will disable margins altogether. With
+ * these calculations, Margins will plainly expand H/VDisplay, and we don't
+ * want that. -- libv
+ *
+ */
+RRModePtr
+xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
+             Bool Interlaced)
+{
+    /* 1) top/bottom margin size (% of height) - default: 1.8 */
+#define CVT_MARGIN_PERCENTAGE 1.8
+
+    /* 2) character cell horizontal granularity (pixels) - default 8 */
+#define CVT_H_GRANULARITY 8
+
+    /* 4) Minimum vertical porch (lines) - default 3 */
+#define CVT_MIN_V_PORCH 3
+
+    /* 4) Minimum number of vertical back porch lines - default 6 */
+#define CVT_MIN_V_BPORCH 6
+
+    /* Pixel Clock step (kHz) */
+#define CVT_CLOCK_STEP 250
+
+    Bool Margins = FALSE;
+    float VFieldRate, HPeriod;
+    int HDisplayRnd, HMargin;
+    int VDisplayRnd, VMargin, VSync;
+    float Interlace;            /* Please rename this */
+    char name[128];
+    xRRModeInfo modeinfo;
+
+    memset(&modeinfo, 0, sizeof modeinfo);
+
+    /* CVT default is 60.0Hz */
+    if (!VRefresh)
+        VRefresh = 60.0;
+
+    /* 1. Required field rate */
+    if (Interlaced)
+        VFieldRate = VRefresh * 2;
+    else
+        VFieldRate = VRefresh;
+
+    /* 2. Horizontal pixels */
+    HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
+
+    /* 3. Determine left and right borders */
+    if (Margins) {
+        /* right margin is actually exactly the same as left */
+        HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+        HMargin -= HMargin % CVT_H_GRANULARITY;
+    }
+    else
+        HMargin = 0;
+
+    /* 4. Find total active pixels */
+    modeinfo.width = HDisplayRnd + 2 * HMargin;
+
+    /* 5. Find number of lines per field */
+    if (Interlaced)
+        VDisplayRnd = VDisplay / 2;
+    else
+        VDisplayRnd = VDisplay;
+
+    /* 6. Find top and bottom margins */
+    /* nope. */
+    if (Margins)
+        /* top and bottom margins are equal again. */
+        VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+    else
+        VMargin = 0;
+
+    modeinfo.height = VDisplay + 2 * VMargin;
+
+    /* 7. Interlace */
+    if (Interlaced)
+        Interlace = 0.5;
+    else
+        Interlace = 0.0;
+
+    /* Determine VSync Width from aspect ratio */
+    if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
+        VSync = 4;
+    else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
+        VSync = 5;
+    else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
+        VSync = 6;
+    else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
+        VSync = 7;
+    else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
+        VSync = 7;
+    else                        /* Custom */
+        VSync = 10;
+
+    if (!Reduced) {             /* simplified GTF calculation */
+
+        /* 4) Minimum time of vertical sync + back porch interval (µs)
+         * default 550.0 */
+#define CVT_MIN_VSYNC_BP 550.0
+
+        /* 3) Nominal HSync width (% of line period) - default 8 */
+#define CVT_HSYNC_PERCENTAGE 8
+
+        float HBlankPercentage;
+        int VSyncAndBackPorch, VBackPorch;
+        int HBlank;
+
+        /* 8. Estimated Horizontal period */
+        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
+            (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
+
+        /* 9. Find number of lines in sync + backporch */
+        if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) <
+            (VSync + CVT_MIN_V_PORCH))
+            VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
+        else
+            VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1;
+
+        /* 10. Find number of lines in back porch */
+        VBackPorch = VSyncAndBackPorch - VSync;
+        (void) VBackPorch;
+
+        /* 11. Find total number of lines in vertical field */
+        modeinfo.vTotal =
+            VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace +
+            CVT_MIN_V_PORCH;
+
+        /* 5) Definition of Horizontal blanking time limitation */
+        /* Gradient (%/kHz) - default 600 */
+#define CVT_M_FACTOR 600
+
+        /* Offset (%) - default 40 */
+#define CVT_C_FACTOR 40
+
+        /* Blanking time scaling factor - default 128 */
+#define CVT_K_FACTOR 128
+
+        /* Scaling factor weighting - default 20 */
+#define CVT_J_FACTOR 20
+
+#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
+#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
+        CVT_J_FACTOR
+
+        /* 12. Find ideal blanking duty cycle from formula */
+        HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
+
+        /* 13. Blanking time */
+        if (HBlankPercentage < 20)
+            HBlankPercentage = 20;
+
+        HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage);
+        HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
+
+        /* 14. Find total number of pixels in a line. */
+        modeinfo.hTotal = modeinfo.width + HBlank;
+
+        /* Fill in HSync values */
+        modeinfo.hSyncEnd = modeinfo.width + HBlank / 2;
+
+        modeinfo.hSyncStart = modeinfo.hSyncEnd -
+            (modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100;
+        modeinfo.hSyncStart += CVT_H_GRANULARITY -
+            modeinfo.hSyncStart % CVT_H_GRANULARITY;
+
+        /* Fill in VSync values */
+        modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH;
+        modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
+
+    }
+    else {                      /* Reduced blanking */
+        /* Minimum vertical blanking interval time (µs) - default 460 */
+#define CVT_RB_MIN_VBLANK 460.0
+
+        /* Fixed number of clocks for horizontal sync */
+#define CVT_RB_H_SYNC 32.0
+
+        /* Fixed number of clocks for horizontal blanking */
+#define CVT_RB_H_BLANK 160.0
+
+        /* Fixed number of lines for vertical front porch - default 3 */
+#define CVT_RB_VFPORCH 3
+
+        int VBILines;
+
+        /* 8. Estimate Horizontal period. */
+        HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
+            (VDisplayRnd + 2 * VMargin);
+
+        /* 9. Find number of lines in vertical blanking */
+        VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
+
+        /* 10. Check if vertical blanking is sufficient */
+        if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
+            VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
+
+        /* 11. Find total number of lines in vertical field */
+        modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
+
+        /* 12. Find total number of pixels in a line */
+        modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK;
+
+        /* Fill in HSync values */
+        modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2;
+        modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC;
+
+        /* Fill in VSync values */
+        modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH;
+        modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
+    }
+
+    /* 15/13. Find pixel clock frequency (kHz for xf86) */
+    modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod;
+    modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP;
+    modeinfo.dotClock *= 1000.0;
+#if 0
+    /* 16/14. Find actual Horizontal Frequency (kHz) */
+    modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal);
+#endif
+
+#if 0
+    /* 17/15. Find actual Field rate */
+    modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) /
+        ((float) (modeinfo.hTotal * modeinfo.vTotal));
+#endif
+
+    /* 18/16. Find actual vertical frame frequency */
+    /* ignore - just set the mode flag for interlaced */
+    if (Interlaced)
+        modeinfo.vTotal *= 2;
+
+    if (Reduced)
+        modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative;
+    else
+        modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive;
+
+    if (Interlaced)
+        modeinfo.modeFlags |= RR_Interlace;
+
+    snprintf(name, sizeof name, "%dx%d@%.1fHz",
+             modeinfo.width, modeinfo.height, VRefresh);
+    modeinfo.nameLength = strlen(name);
+
+    return RRModeGet(&modeinfo, name);
+}
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
new file mode 100644
index 0000000..990cb82
--- /dev/null
+++ b/hw/xwayland/xwayland-input.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2008 Kristian Høgsberg
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "xwayland.h"
+
+#include <linux/input.h>
+
+#include <sys/mman.h>
+#include <xkbsrv.h>
+#include <xserver-properties.h>
+#include <inpututils.h>
+
+static void
+xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+    /* Nothing to do, dix handles all settings */
+}
+
+static int
+xwl_pointer_proc(DeviceIntPtr device, int what)
+{
+#define NBUTTONS 10
+#define NAXES 2
+    BYTE map[NBUTTONS + 1];
+    int i = 0;
+    Atom btn_labels[NBUTTONS] = { 0 };
+    Atom axes_labels[NAXES] = { 0 };
+
+    switch (what) {
+    case DEVICE_INIT:
+        device->public.on = FALSE;
+
+        for (i = 1; i <= NBUTTONS; i++)
+            map[i] = i;
+
+        btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+        btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+        btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+        btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
+        btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+        btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+        btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+        /* don't know about the rest */
+
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+
+        if (!InitValuatorClassDeviceStruct(device, 2, btn_labels,
+                                           GetMotionHistorySize(), Absolute))
+            return BadValue;
+
+        /* Valuators */
+        InitValuatorAxisStruct(device, 0, axes_labels[0],
+                               0, 0xFFFF, 10000, 0, 10000, Absolute);
+        InitValuatorAxisStruct(device, 1, axes_labels[1],
+                               0, 0xFFFF, 10000, 0, 10000, Absolute);
+
+        if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control))
+            return BadValue;
+
+        if (!InitButtonClassDeviceStruct(device, 3, btn_labels, map))
+            return BadValue;
+
+        return Success;
+
+    case DEVICE_ON:
+        device->public.on = TRUE;
+        return Success;
+
+    case DEVICE_OFF:
+    case DEVICE_CLOSE:
+        device->public.on = FALSE;
+        return Success;
+    }
+
+    return BadMatch;
+
+#undef NBUTTONS
+#undef NAXES
+}
+
+static void
+xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl)
+{
+}
+
+static int
+xwl_keyboard_proc(DeviceIntPtr device, int what)
+{
+    struct xwl_seat *xwl_seat = device->public.devicePrivate;
+    int len;
+
+    switch (what) {
+    case DEVICE_INIT:
+        device->public.on = FALSE;
+        if (xwl_seat->keymap)
+            len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size);
+        else
+            len = 0;
+        if (!InitKeyboardDeviceStructFromString(device, xwl_seat->keymap,
+                                                len,
+                                                NULL, xwl_keyboard_control))
+            return BadValue;
+
+        return Success;
+    case DEVICE_ON:
+        device->public.on = TRUE;
+        return Success;
+
+    case DEVICE_OFF:
+    case DEVICE_CLOSE:
+        device->public.on = FALSE;
+        return Success;
+    }
+
+    return BadMatch;
+}
+
+static void
+pointer_handle_enter(void *data, struct wl_pointer *pointer,
+                     uint32_t serial, struct wl_surface *surface,
+                     wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr dev = xwl_seat->pointer;
+    int i;
+    int sx = wl_fixed_to_int(sx_w);
+    int sy = wl_fixed_to_int(sy_w);
+    ScreenPtr pScreen = xwl_seat->xwl_screen->screen;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+    xwl_seat->pointer_enter_serial = serial;
+
+    xwl_seat->focus_window = wl_surface_get_user_data(surface);
+
+    (*pScreen->SetCursorPosition) (dev, pScreen, sx, sy, TRUE);
+    CheckMotion(NULL, GetMaster(dev, MASTER_POINTER));
+
+    /* Ideally, X clients shouldn't see these button releases.  When
+     * the pointer leaves a window with buttons down, it means that
+     * the wayland compositor has grabbed the pointer.  The button
+     * release event is consumed by whatever grab in the compositor
+     * and won't be sent to clients (the X server is a client).
+     * However, we need to reset X's idea of which buttons are up and
+     * down, and they're all up (by definition) when the pointer
+     * enters a window.  We should figure out a way to swallow these
+     * events, perhaps using an X grab whenever the pointer is not in
+     * any X window, but for now just send the events. */
+    valuator_mask_zero(&mask);
+    for (i = 0; i < dev->button->numButtons; i++)
+        if (BitIsOn(dev->button->down, i))
+            QueuePointerEvents(xwl_seat->pointer, ButtonRelease, i, 0, &mask);
+}
+
+static void
+pointer_handle_leave(void *data, struct wl_pointer *pointer,
+                     uint32_t serial, struct wl_surface *surface)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr dev = xwl_seat->pointer;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    xwl_seat->focus_window = NULL;
+    CheckMotion(NULL, GetMaster(dev, MASTER_POINTER));
+}
+
+static void
+pointer_handle_motion(void *data, struct wl_pointer *pointer,
+                      uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+    struct xwl_seat *xwl_seat = data;
+    int32_t dx, dy;
+    int sx = wl_fixed_to_int(sx_w);
+    int sy = wl_fixed_to_int(sy_w);
+    ValuatorMask mask;
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    dx = xwl_seat->focus_window->window->drawable.x;
+    dy = xwl_seat->focus_window->window->drawable.y;
+
+    valuator_mask_zero(&mask);
+    valuator_mask_set(&mask, 0, dx + sx);
+    valuator_mask_set(&mask, 1, dy + sy);
+
+    QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0,
+                       POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+}
+
+static void
+pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
+                      uint32_t time, uint32_t button, uint32_t state)
+{
+    struct xwl_seat *xwl_seat = data;
+    int index;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    switch (button) {
+    case BTN_MIDDLE:
+        index = 2;
+        break;
+    case BTN_RIGHT:
+        index = 3;
+        break;
+    default:
+        index = button - BTN_LEFT + 1;
+        break;
+    }
+
+    valuator_mask_zero(&mask);
+    QueuePointerEvents(xwl_seat->pointer,
+                       state ? ButtonPress : ButtonRelease, index, 0, &mask);
+}
+
+static void
+pointer_handle_axis(void *data, struct wl_pointer *pointer,
+                    uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+    struct xwl_seat *xwl_seat = data;
+    int index, count;
+    int i, val;
+    const int divisor = 10;
+    ValuatorMask mask;
+
+    if (time - xwl_seat->scroll_time > 2000) {
+        xwl_seat->vertical_scroll = 0;
+        xwl_seat->horizontal_scroll = 0;
+    }
+    xwl_seat->scroll_time = time;
+
+    /* FIXME: Need to do proper smooth scrolling here! */
+    switch (axis) {
+    case WL_POINTER_AXIS_VERTICAL_SCROLL:
+        xwl_seat->vertical_scroll += value / divisor;
+        val = wl_fixed_to_int(xwl_seat->vertical_scroll);
+        xwl_seat->vertical_scroll -= wl_fixed_from_int(val);
+
+        if (val <= -1)
+            index = 4;
+        else if (val >= 1)
+            index = 5;
+        else
+            return;
+        break;
+    case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+        xwl_seat->horizontal_scroll += value / divisor;
+        val = wl_fixed_to_int(xwl_seat->horizontal_scroll);
+        xwl_seat->horizontal_scroll -= wl_fixed_from_int(val);
+
+        if (val <= -1)
+            index = 6;
+        else if (val >= 1)
+            index = 7;
+        else
+            return;
+        break;
+    default:
+        return;
+    }
+
+    valuator_mask_zero(&mask);
+
+    count = abs(val);
+    for (i = 0; i < count; i++) {
+        QueuePointerEvents(xwl_seat->pointer, ButtonPress, index, 0, &mask);
+        QueuePointerEvents(xwl_seat->pointer, ButtonRelease, index, 0, &mask);
+    }
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+    pointer_handle_enter,
+    pointer_handle_leave,
+    pointer_handle_motion,
+    pointer_handle_button,
+    pointer_handle_axis,
+};
+
+static void
+keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial,
+                    uint32_t time, uint32_t key, uint32_t state)
+{
+    struct xwl_seat *xwl_seat = data;
+    uint32_t *k, *end;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    end = (uint32_t *) ((char *) xwl_seat->keys.data + xwl_seat->keys.size);
+    for (k = xwl_seat->keys.data; k < end; k++) {
+        if (*k == key)
+            *k = *--end;
+    }
+    xwl_seat->keys.size = (char *) end - (char *) xwl_seat->keys.data;
+    if (state) {
+        k = wl_array_add(&xwl_seat->keys, sizeof *k);
+        *k = key;
+    }
+
+    valuator_mask_zero(&mask);
+    QueueKeyboardEvents(xwl_seat->keyboard,
+                        state ? KeyPress : KeyRelease, key + 8, &mask);
+}
+
+static void
+keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
+                       uint32_t format, int fd, uint32_t size)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr master;
+    XkbDescPtr xkb;
+    XkbChangesRec changes = { 0 };
+
+    if (xwl_seat->keymap)
+        munmap(xwl_seat->keymap, xwl_seat->keymap_size);
+
+    xwl_seat->keymap_size = size;
+    xwl_seat->keymap = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+    if (xwl_seat->keymap == MAP_FAILED) {
+        xwl_seat->keymap_size = 0;
+        xwl_seat->keymap = NULL;
+        goto out;
+    }
+
+    xkb = XkbCompileKeymapFromString(xwl_seat->keyboard, xwl_seat->keymap,
+                                     strnlen(xwl_seat->keymap,
+                                             xwl_seat->keymap_size));
+    if (!xkb)
+        goto out;
+
+    XkbUpdateDescActions(xkb, xkb->min_key_code, XkbNumKeys(xkb), &changes);
+
+    if (xwl_seat->keyboard->key)
+        /* Keep the current controls */
+        XkbCopyControls(xkb, xwl_seat->keyboard->key->xkbInfo->desc);
+
+    XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb);
+
+    master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
+    if (master && master->lastSlave == xwl_seat->keyboard)
+        XkbDeviceApplyKeymap(master, xkb);
+
+    XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE);
+
+ out:
+    close(fd);
+}
+
+static void
+keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
+                      uint32_t serial,
+                      struct wl_surface *surface, struct wl_array *keys)
+{
+    struct xwl_seat *xwl_seat = data;
+    ValuatorMask mask;
+    uint32_t *k;
+
+    xwl_seat->xwl_screen->serial = serial;
+    xwl_seat->keyboard_focus = surface;
+
+    wl_array_copy(&xwl_seat->keys, keys);
+    valuator_mask_zero(&mask);
+    wl_array_for_each(k, &xwl_seat->keys)
+        QueueKeyboardEvents(xwl_seat->keyboard, KeyPress, *k + 8, &mask);
+}
+
+static void
+keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
+                      uint32_t serial, struct wl_surface *surface)
+{
+    struct xwl_seat *xwl_seat = data;
+    ValuatorMask mask;
+    uint32_t *k;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    valuator_mask_zero(&mask);
+    wl_array_for_each(k, &xwl_seat->keys)
+        QueueKeyboardEvents(xwl_seat->keyboard, KeyRelease, *k + 8, &mask);
+
+    xwl_seat->keyboard_focus = NULL;
+}
+
+static void
+keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
+                          uint32_t serial, uint32_t mods_depressed,
+                          uint32_t mods_latched, uint32_t mods_locked,
+                          uint32_t group)
+{
+    struct xwl_seat *xwl_seat = data;
+    DeviceIntPtr dev;
+    XkbStateRec old_state, *new_state;
+    xkbStateNotify sn;
+    CARD16 changed;
+
+    /* We don't need any of this while we have keyboard focus since
+       the regular key event processing already takes care of setting
+       our internal state correctly. */
+    if (xwl_seat->keyboard_focus)
+        return;
+
+    for (dev = inputInfo.devices; dev; dev = dev->next) {
+        if (dev != xwl_seat->keyboard &&
+            dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD))
+            continue;
+
+        old_state = dev->key->xkbInfo->state;
+        new_state = &dev->key->xkbInfo->state;
+
+        new_state->locked_group = group & XkbAllGroupsMask;
+        new_state->locked_mods = mods_locked & XkbAllModifiersMask;
+        XkbLatchModifiers(dev, XkbAllModifiersMask,
+                          mods_latched & XkbAllModifiersMask);
+
+        XkbComputeDerivedState(dev->key->xkbInfo);
+
+        changed = XkbStateChangedFlags(&old_state, new_state);
+        if (!changed)
+            continue;
+
+        sn.keycode = 0;
+        sn.eventType = 0;
+        sn.requestMajor = XkbReqCode;
+        sn.requestMinor = X_kbLatchLockState;   /* close enough */
+        sn.changed = changed;
+        XkbSendStateNotify(dev, &sn);
+    }
+}
+
+static const struct wl_keyboard_listener keyboard_listener = {
+    keyboard_handle_keymap,
+    keyboard_handle_enter,
+    keyboard_handle_leave,
+    keyboard_handle_key,
+    keyboard_handle_modifiers,
+};
+
+static DeviceIntPtr
+add_device(struct xwl_seat *xwl_seat,
+           const char *driver, DeviceProc device_proc)
+{
+    DeviceIntPtr dev = NULL;
+    static Atom type_atom;
+    char name[32];
+
+    dev = AddInputDevice(serverClient, device_proc, TRUE);
+    if (dev == NULL)
+        return NULL;
+
+    if (type_atom == None)
+        type_atom = MakeAtom(driver, strlen(driver), TRUE);
+    snprintf(name, sizeof name, "%s:%d", driver, xwl_seat->id);
+    AssignTypeAndName(dev, type_atom, name);
+    dev->public.devicePrivate = xwl_seat;
+    dev->type = SLAVE;
+    dev->spriteInfo->spriteOwner = FALSE;
+
+    return dev;
+}
+
+static void
+seat_handle_capabilities(void *data, struct wl_seat *seat,
+                         enum wl_seat_capability caps)
+{
+    struct xwl_seat *xwl_seat = data;
+
+    if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->pointer == NULL) {
+        xwl_seat->wl_pointer = wl_seat_get_pointer(seat);
+        wl_pointer_add_listener(xwl_seat->wl_pointer,
+                                &pointer_listener, xwl_seat);
+        xwl_seat_set_cursor(xwl_seat);
+        xwl_seat->pointer =
+            add_device(xwl_seat, "xwayland-pointer", xwl_pointer_proc);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->pointer) {
+        wl_pointer_release(xwl_seat->wl_pointer);
+        RemoveDevice(xwl_seat->pointer, FALSE);
+        xwl_seat->pointer = NULL;
+    }
+
+    if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->keyboard == NULL) {
+        xwl_seat->wl_keyboard = wl_seat_get_keyboard(seat);
+        wl_keyboard_add_listener(xwl_seat->wl_keyboard,
+                                 &keyboard_listener, xwl_seat);
+        xwl_seat->keyboard =
+            add_device(xwl_seat, "xwayland-keyboard", xwl_keyboard_proc);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && xwl_seat->keyboard) {
+        wl_keyboard_release(xwl_seat->wl_keyboard);
+        RemoveDevice(xwl_seat->keyboard, FALSE);
+        xwl_seat->keyboard = NULL;
+    }
+
+    xwl_seat->xwl_screen->expecting_event--;
+    /* FIXME: Touch ... */
+}
+
+static void
+seat_handle_name(void *data, struct wl_seat *seat,
+		 const char *name)
+{
+
+}
+
+static const struct wl_seat_listener seat_listener = {
+    seat_handle_capabilities,
+    seat_handle_name
+};
+
+static void
+create_input_device(struct xwl_screen *xwl_screen, uint32_t id)
+{
+    struct xwl_seat *xwl_seat;
+
+    xwl_seat = calloc(sizeof *xwl_seat, 1);
+    if (xwl_seat == NULL) {
+        ErrorF("create_input ENOMEM");
+        return;
+    }
+
+    xwl_seat->xwl_screen = xwl_screen;
+    xorg_list_add(&xwl_seat->link, &xwl_screen->seat_list);
+
+    xwl_seat->seat =
+        wl_registry_bind(xwl_screen->registry, id, &wl_seat_interface, 3);
+    xwl_seat->id = id;
+
+    xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor);
+    wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat);
+    wl_array_init(&xwl_seat->keys);
+}
+
+void
+xwl_seat_destroy(struct xwl_seat *xwl_seat)
+{
+    RemoveDevice(xwl_seat->pointer, FALSE);
+    RemoveDevice(xwl_seat->keyboard, FALSE);
+    wl_seat_destroy(xwl_seat->seat);
+    wl_surface_destroy(xwl_seat->cursor);
+    wl_array_release(&xwl_seat->keys);
+    free(xwl_seat);
+}
+
+static void
+input_handler(void *data, struct wl_registry *registry, uint32_t id,
+              const char *interface, uint32_t version)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    if (strcmp(interface, "wl_seat") == 0 && version >= 3) {
+        create_input_device(xwl_screen, id);
+        xwl_screen->expecting_event++;
+    }
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+}
+
+static const struct wl_registry_listener input_listener = {
+    input_handler,
+    global_remove,
+};
+
+Bool
+LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+    return TRUE;
+}
+
+void
+ProcessInputEvents(void)
+{
+    mieqProcessInputEvents();
+}
+
+void
+DDXRingBell(int volume, int pitch, int duration)
+{
+}
+
+static WindowPtr
+xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y)
+{
+    struct xwl_seat *xwl_seat = NULL;
+    DeviceIntPtr device;
+
+    for (device = inputInfo.devices; device; device = device->next) {
+        if (device->deviceProc == xwl_pointer_proc &&
+            device->spriteInfo->sprite == sprite) {
+            xwl_seat = device->public.devicePrivate;
+            break;
+        }
+    }
+
+    if (xwl_seat == NULL) {
+        /* XTEST device */
+        sprite->spriteTraceGood = 1;
+        return sprite->spriteTrace[0];
+    }
+
+    if (xwl_seat->focus_window) {
+        sprite->spriteTraceGood = 2;
+        sprite->spriteTrace[1] = xwl_seat->focus_window->window;
+        return miSpriteTrace(sprite, x, y);
+    }
+    else {
+        sprite->spriteTraceGood = 1;
+        return sprite->spriteTrace[0];
+    }
+}
+
+void
+InitInput(int argc, char *argv[])
+{
+    ScreenPtr pScreen = screenInfo.screens[0];
+    struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
+
+    mieqInit();
+
+    xwl_screen->input_registry = wl_display_get_registry(xwl_screen->display);
+    wl_registry_add_listener(xwl_screen->input_registry, &input_listener,
+                             xwl_screen);
+
+    xwl_screen->XYToWindow = pScreen->XYToWindow;
+    pScreen->XYToWindow = xwl_xy_to_window;
+
+    xwl_screen->expecting_event = 0;
+    wl_display_roundtrip(xwl_screen->display);
+    while (xwl_screen->expecting_event)
+        wl_display_roundtrip(xwl_screen->display);
+}
+
+void
+CloseInput(void)
+{
+    mieqFini();
+}
diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
new file mode 100644
index 0000000..778914c
--- /dev/null
+++ b/hw/xwayland/xwayland-output.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "xwayland.h"
+#include <randrstr.h>
+
+static Rotation
+wl_transform_to_xrandr(enum wl_output_transform transform)
+{
+    switch (transform) {
+    default:
+    case WL_OUTPUT_TRANSFORM_NORMAL:
+        return RR_Rotate_0;
+    case WL_OUTPUT_TRANSFORM_90:
+        return RR_Rotate_90;
+    case WL_OUTPUT_TRANSFORM_180:
+        return RR_Rotate_180;
+    case WL_OUTPUT_TRANSFORM_270:
+        return RR_Rotate_270;
+    case WL_OUTPUT_TRANSFORM_FLIPPED:
+        return RR_Reflect_X | RR_Rotate_0;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+        return RR_Reflect_X | RR_Rotate_90;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+        return RR_Reflect_X | RR_Rotate_180;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+        return RR_Reflect_X | RR_Rotate_270;
+    }
+}
+
+static int
+wl_subpixel_to_xrandr(int subpixel)
+{
+    switch (subpixel) {
+    default:
+    case WL_OUTPUT_SUBPIXEL_UNKNOWN:
+        return SubPixelUnknown;
+    case WL_OUTPUT_SUBPIXEL_NONE:
+        return SubPixelNone;
+    case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
+        return SubPixelHorizontalRGB;
+    case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
+        return SubPixelHorizontalBGR;
+    case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
+        return SubPixelVerticalRGB;
+    case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
+        return SubPixelVerticalBGR;
+    }
+}
+
+static void
+output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
+                       int physical_width, int physical_height, int subpixel,
+                       const char *make, const char *model, int transform)
+{
+    struct xwl_output *xwl_output = data;
+
+    RROutputSetPhysicalSize(xwl_output->randr_output,
+                            physical_width, physical_height);
+    RROutputSetSubpixelOrder(xwl_output->randr_output,
+                             wl_subpixel_to_xrandr(subpixel));
+    xwl_output->x = x;
+    xwl_output->y = y;
+
+    xwl_output->rotation = wl_transform_to_xrandr(transform);
+}
+
+static void
+output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
+                   int width, int height, int refresh)
+{
+    struct xwl_output *xwl_output = data;
+    RRModePtr randr_mode;
+
+    if (!(flags & WL_OUTPUT_MODE_CURRENT))
+        return;
+
+    xwl_output->width = width;
+    xwl_output->height = height;
+
+    randr_mode = xwayland_cvt(width, height, refresh / 1000.0, 0, 0);
+
+    RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1);
+
+    RRCrtcNotify(xwl_output->randr_crtc, randr_mode,
+                 xwl_output->x, xwl_output->y,
+                 xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
+}
+
+static void
+output_handle_done(void *data, struct wl_output *wl_output)
+{
+    struct xwl_output *xwl_output = data;
+    struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+    int width, height;
+
+    xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
+
+    width = 0;
+    height = 0;
+    xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
+        if (width < xwl_output->x + xwl_output->width)
+            width = xwl_output->x + xwl_output->width;
+        if (height < xwl_output->y + xwl_output->height)
+            height = xwl_output->y + xwl_output->height;
+    }
+
+    xwl_screen->width = width;
+    xwl_screen->height = height;
+    RRScreenSizeNotify(xwl_screen->screen);
+
+    xwl_screen->expecting_event--;
+}
+
+static void
+output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor)
+{
+}
+
+static const struct wl_output_listener output_listener = {
+    output_handle_geometry,
+    output_handle_mode,
+    output_handle_done,
+    output_handle_scale
+};
+
+struct xwl_output *
+xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
+{
+    struct xwl_output *xwl_output;
+    static int serial;
+    char name[256];
+
+    xwl_output = calloc(sizeof *xwl_output, 1);
+    if (xwl_output == NULL) {
+        ErrorF("create_output ENOMEM");
+        return NULL;
+    }
+
+    xwl_output->output = wl_registry_bind(xwl_screen->registry, id,
+                                          &wl_output_interface, 2);
+    wl_output_add_listener(xwl_output->output, &output_listener, xwl_output);
+
+    if (snprintf(name, sizeof name, "XWAYLAND%d", serial++) < 0) {
+        ErrorF("create_output ENOMEM");
+        free(xwl_output);
+        return NULL;
+    }
+
+    xwl_output->xwl_screen = xwl_screen;
+    xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output);
+    xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name,
+                                              strlen(name), xwl_output);
+    RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
+    RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
+    RROutputSetConnection(xwl_output->randr_output, RR_Connected);
+
+    return xwl_output;
+}
+
+void
+xwl_output_destroy(struct xwl_output *xwl_output)
+{
+    wl_output_destroy(xwl_output->output);
+    RRCrtcDestroy(xwl_output->randr_crtc);
+    RROutputDestroy(xwl_output->randr_output);
+    free(xwl_output);
+}
+
+static Bool
+xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations)
+{
+    *rotations = 0;
+
+    return TRUE;
+}
+
+static Bool
+xwl_randr_set_config(ScreenPtr pScreen,
+                     Rotation rotation, int rate, RRScreenSizePtr pSize)
+{
+    return FALSE;
+}
+
+Bool
+xwl_screen_init_output(struct xwl_screen *xwl_screen)
+{
+    rrScrPrivPtr rp;
+
+    if (!RRScreenInit(xwl_screen->screen))
+        return FALSE;
+
+    RRScreenSetSizeRange(xwl_screen->screen, 320, 200, 8192, 8192);
+
+    rp = rrGetScrPriv(xwl_screen->screen);
+    rp->rrGetInfo = xwl_randr_get_info;
+    rp->rrSetConfig = xwl_randr_set_config;
+
+    return TRUE;
+}
diff --git a/hw/xwayland/xwayland-shm.c b/hw/xwayland/xwayland-shm.c
new file mode 100644
index 0000000..2d0ce3e
--- /dev/null
+++ b/hw/xwayland/xwayland-shm.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2012 Collabora, Ltd.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "xwayland.h"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+struct xwl_pixmap {
+    struct wl_buffer *buffer;
+    int fd;
+    void *data;
+    size_t size;
+};
+
+#ifndef HAVE_MKOSTEMP
+static int
+set_cloexec_or_close(int fd)
+{
+    long flags;
+
+    if (fd == -1)
+        return -1;
+
+    flags = fcntl(fd, F_GETFD);
+    if (flags == -1)
+        goto err;
+
+    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+        goto err;
+
+    return fd;
+
+ err:
+    close(fd);
+    return -1;
+}
+#endif
+
+static int
+create_tmpfile_cloexec(char *tmpname)
+{
+    int fd;
+
+#ifdef HAVE_MKOSTEMP
+    fd = mkostemp(tmpname, O_CLOEXEC);
+    if (fd >= 0)
+        unlink(tmpname);
+#else
+    fd = mkstemp(tmpname);
+    if (fd >= 0) {
+        fd = set_cloexec_or_close(fd);
+        unlink(tmpname);
+    }
+#endif
+
+    return fd;
+}
+
+/*
+ * Create a new, unique, anonymous file of the given size, and
+ * return the file descriptor for it. The file descriptor is set
+ * CLOEXEC. The file is immediately suitable for mmap()'ing
+ * the given size at offset zero.
+ *
+ * The file should not have a permanent backing store like a disk,
+ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
+ *
+ * The file name is deleted from the file system.
+ *
+ * The file is suitable for buffer sharing between processes by
+ * transmitting the file descriptor over Unix sockets using the
+ * SCM_RIGHTS methods.
+ *
+ * If the C library implements posix_fallocate(), it is used to
+ * guarantee that disk space is available for the file at the
+ * given size. If disk space is insufficent, errno is set to ENOSPC.
+ * If posix_fallocate() is not supported, program may receive
+ * SIGBUS on accessing mmap()'ed file contents instead.
+ */
+static int
+os_create_anonymous_file(off_t size)
+{
+    static const char template[] = "/weston-shared-XXXXXX";
+    const char *path;
+    char *name;
+    int fd;
+    int ret;
+
+    path = getenv("XDG_RUNTIME_DIR");
+    if (!path) {
+        errno = ENOENT;
+        return -1;
+    }
+
+    name = malloc(strlen(path) + sizeof(template));
+    if (!name)
+        return -1;
+
+    strcpy(name, path);
+    strcat(name, template);
+
+    fd = create_tmpfile_cloexec(name);
+
+    free(name);
+
+    if (fd < 0)
+        return -1;
+
+#ifdef HAVE_POSIX_FALLOCATE
+    ret = posix_fallocate(fd, 0, size);
+    if (ret != 0) {
+        close(fd);
+        errno = ret;
+        return -1;
+    }
+#else
+    ret = ftruncate(fd, size);
+    if (ret < 0) {
+        close(fd);
+        return -1;
+    }
+#endif
+
+    return fd;
+}
+
+static uint32_t
+shm_format_for_depth(int depth)
+{
+    switch (depth) {
+    case 32:
+        return WL_SHM_FORMAT_ARGB8888;
+    case 24:
+    default:
+        return WL_SHM_FORMAT_XRGB8888;
+#ifdef WL_SHM_FORMAT_RGB565
+    case 16:
+        /* XXX: Check run-time protocol version too */
+        return WL_SHM_FORMAT_RGB565;
+#endif
+    }
+}
+
+PixmapPtr
+xwl_shm_create_pixmap(ScreenPtr screen,
+                      int width, int height, int depth, unsigned int hint)
+{
+    PixmapPtr pixmap;
+    struct xwl_pixmap *xwl_pixmap;
+    size_t size, stride;
+
+    if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE ||
+        (width == 0 && height == 0) || depth < 15)
+        return fbCreatePixmap(screen, width, height, depth, hint);
+
+    pixmap = fbCreatePixmap(screen, 0, 0, depth, hint);
+    if (!pixmap)
+        return NULL;
+
+    xwl_pixmap = malloc(sizeof *xwl_pixmap);
+    if (xwl_pixmap == NULL)
+        goto err_destroy_pixmap;
+
+    stride = PixmapBytePad(width, depth);
+    size = stride * height;
+    xwl_pixmap->buffer = NULL;
+    xwl_pixmap->size = size;
+    xwl_pixmap->fd = os_create_anonymous_file(size);
+    if (xwl_pixmap->fd < 0)
+        goto err_free_xwl_pixmap;
+
+    xwl_pixmap->data = mmap(NULL, size, PROT_READ | PROT_WRITE,
+                                  MAP_SHARED, xwl_pixmap->fd, 0);
+    if (xwl_pixmap->data == MAP_FAILED)
+        goto err_close_fd;
+
+    if (!(*screen->ModifyPixmapHeader) (pixmap, width, height, depth,
+                                        BitsPerPixel(depth),
+                                        stride, xwl_pixmap->data))
+        goto err_munmap;
+
+    xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+    return pixmap;
+
+ err_munmap:
+    munmap(xwl_pixmap->data, size);
+ err_close_fd:
+    close(xwl_pixmap->fd);
+ err_free_xwl_pixmap:
+    free(xwl_pixmap);
+ err_destroy_pixmap:
+    fbDestroyPixmap(pixmap);
+
+    return NULL;
+}
+
+Bool
+xwl_shm_destroy_pixmap(PixmapPtr pixmap)
+{
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+    if (xwl_pixmap && pixmap->refcnt == 1) {
+        if (xwl_pixmap->buffer)
+            wl_buffer_destroy(xwl_pixmap->buffer);
+        munmap(xwl_pixmap->data, xwl_pixmap->size);
+        close(xwl_pixmap->fd);
+        free(xwl_pixmap);
+    }
+
+    return fbDestroyPixmap(pixmap);
+}
+
+struct wl_buffer *
+xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    struct wl_shm_pool *pool;
+    uint32_t format;
+
+    if (xwl_pixmap->buffer)
+        return xwl_pixmap->buffer;
+
+    pool = wl_shm_create_pool(xwl_screen->shm,
+                              xwl_pixmap->fd, xwl_pixmap->size);
+
+    format = shm_format_for_depth(pixmap->drawable.depth);
+    xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0,
+                                                   pixmap->drawable.width,
+                                                   pixmap->drawable.height,
+                                                   pixmap->devKind, format);
+
+    wl_shm_pool_destroy(pool);
+
+    return xwl_pixmap->buffer;
+}
+
+Bool
+xwl_shm_create_screen_resources(ScreenPtr screen)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    int ret;
+
+    screen->CreateScreenResources = xwl_screen->CreateScreenResources;
+    ret = (*screen->CreateScreenResources) (screen);
+    xwl_screen->CreateScreenResources = screen->CreateScreenResources;
+    screen->CreateScreenResources = xwl_shm_create_screen_resources;
+
+    if (!ret)
+        return ret;
+
+    if (xwl_screen->rootless)
+        screen->devPrivate =
+            fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
+    else
+        screen->devPrivate =
+            xwl_shm_create_pixmap(screen, screen->width, screen->height,
+                                  screen->rootDepth,
+                                  CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
+
+    return screen->devPrivate != NULL;
+}
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
new file mode 100644
index 0000000..c2c6481
--- /dev/null
+++ b/hw/xwayland/xwayland.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "xwayland.h"
+
+#include <stdio.h>
+
+#include <selection.h>
+#include <micmap.h>
+#include <misyncshm.h>
+#include <compositeext.h>
+#include <glx_extinit.h>
+
+void
+ddxGiveUp(enum ExitCode error)
+{
+}
+
+void
+AbortDDX(enum ExitCode error)
+{
+    ddxGiveUp(error);
+}
+
+void
+OsVendorInit(void)
+{
+}
+
+void
+OsVendorFatalError(const char *f, va_list args)
+{
+}
+
+#if defined(DDXBEFORERESET)
+void
+ddxBeforeReset(void)
+{
+    return;
+}
+#endif
+
+void
+ddxUseMsg(void)
+{
+    ErrorF("-rootless              run rootless, requires wm support\n");
+    ErrorF("-wm fd                 create X client for wm on given fd\n");
+    ErrorF("-listen fd             add give fd as a listen socket\n");
+}
+
+int
+ddxProcessArgument(int argc, char *argv[], int i)
+{
+    if (strcmp(argv[i], "-rootless") == 0) {
+        return 1;
+    }
+    else if (strcmp(argv[i], "-listen") == 0) {
+        NoListenAll = TRUE;
+        return 2;
+    }
+    else if (strcmp(argv[i], "-wm") == 0) {
+        return 2;
+    }
+    else if (strcmp(argv[i], "-shm") == 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static DevPrivateKeyRec xwl_window_private_key;
+static DevPrivateKeyRec xwl_screen_private_key;
+static DevPrivateKeyRec xwl_pixmap_private_key;
+
+struct xwl_screen *
+xwl_screen_get(ScreenPtr screen)
+{
+    return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
+}
+
+static Bool
+xwl_close_screen(ScreenPtr screen)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_output *xwl_output, *next_xwl_output;
+    struct xwl_seat *xwl_seat, *next_xwl_seat;
+
+    xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
+                                  &xwl_screen->output_list, link)
+        xwl_output_destroy(xwl_output);
+
+    xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
+                                  &xwl_screen->seat_list, link)
+        xwl_seat_destroy(xwl_seat);
+
+    wl_display_disconnect(xwl_screen->display);
+
+    screen->CloseScreen = xwl_screen->CloseScreen;
+    free(xwl_screen);
+
+    return screen->CloseScreen(screen);
+}
+
+static void
+damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
+{
+    struct xwl_window *xwl_window = data;
+    struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+
+    xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
+}
+
+static void
+damage_destroy(DamagePtr pDamage, void *data)
+{
+}
+
+static void
+shell_surface_ping(void *data,
+                   struct wl_shell_surface *shell_surface, uint32_t serial)
+{
+    wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+shell_surface_configure(void *data,
+                        struct wl_shell_surface *wl_shell_surface,
+                        uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static void
+shell_surface_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+    shell_surface_ping,
+    shell_surface_configure,
+    shell_surface_popup_done
+};
+
+void
+xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap)
+{
+    dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap);
+}
+
+struct xwl_pixmap *
+xwl_pixmap_get(PixmapPtr pixmap)
+{
+    return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
+}
+
+static void
+send_surface_id_event(struct xwl_window *xwl_window)
+{
+    static const char atom_name[] = "WL_SURFACE_ID";
+    static Atom type_atom;
+    DeviceIntPtr dev;
+    xEvent e;
+
+    if (type_atom == None)
+        type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
+
+    e.u.u.type = ClientMessage;
+    e.u.u.detail = 32;
+    e.u.clientMessage.window = xwl_window->window->drawable.id;
+    e.u.clientMessage.u.l.type = type_atom;
+    e.u.clientMessage.u.l.longs0 =
+        wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
+    e.u.clientMessage.u.l.longs1 = 0;
+    e.u.clientMessage.u.l.longs2 = 0;
+    e.u.clientMessage.u.l.longs3 = 0;
+    e.u.clientMessage.u.l.longs4 = 0;
+
+    dev = PickPointer(serverClient);
+    DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root,
+                          &e, 1, SubstructureRedirectMask, NullGrab);
+}
+
+static Bool
+xwl_realize_window(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen;
+    struct xwl_window *xwl_window;
+    struct wl_region *region;
+    Bool ret;
+
+    xwl_screen = xwl_screen_get(screen);
+
+    screen->RealizeWindow = xwl_screen->RealizeWindow;
+    ret = (*screen->RealizeWindow) (window);
+    xwl_screen->RealizeWindow = screen->RealizeWindow;
+    screen->RealizeWindow = xwl_realize_window;
+
+    if (xwl_screen->rootless && !window->parent) {
+        ErrorF("Clearing root clip\n");
+        RegionNull(&window->clipList);
+        RegionNull(&window->borderClip);
+        RegionNull(&window->winSize);
+    }
+
+    if (xwl_screen->rootless) {
+        if (window->redirectDraw != RedirectDrawManual)
+            return ret;
+    }
+    else {
+        if (window->parent)
+            return ret;
+    }
+
+    xwl_window = calloc(sizeof *xwl_window, 1);
+    xwl_window->xwl_screen = xwl_screen;
+    xwl_window->window = window;
+    xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor);
+    if (xwl_window->surface == NULL) {
+        ErrorF("wl_display_create_surface failed\n");
+        return FALSE;
+    }
+
+    if (!xwl_screen->rootless) {
+        xwl_window->shell_surface =
+            wl_shell_get_shell_surface(xwl_screen->shell, xwl_window->surface);
+        wl_shell_surface_add_listener(xwl_window->shell_surface,
+                                      &shell_surface_listener, xwl_window);
+
+        wl_shell_surface_set_toplevel(xwl_window->shell_surface);
+
+        region = wl_compositor_create_region(xwl_screen->compositor);
+        wl_region_add(region, 0, 0,
+                      window->drawable.width, window->drawable.height);
+        wl_surface_set_opaque_region(xwl_window->surface, region);
+        wl_region_destroy(region);
+    }
+
+    wl_display_flush(xwl_screen->display);
+
+    send_surface_id_event(xwl_window);
+
+    wl_surface_set_user_data(xwl_window->surface, xwl_window);
+
+    dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
+
+    xwl_window->damage =
+        DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
+                     FALSE, screen, xwl_window);
+    DamageRegister(&window->drawable, xwl_window->damage);
+    DamageSetReportAfterOp(xwl_window->damage, TRUE);
+
+    xorg_list_init(&xwl_window->link_damage);
+
+    return ret;
+}
+
+static Bool
+xwl_unrealize_window(WindowPtr window)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+    struct xwl_screen *xwl_screen;
+    struct xwl_window *xwl_window;
+    struct xwl_seat *xwl_seat;
+    Bool ret;
+
+    xwl_screen = xwl_screen_get(screen);
+
+    xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+        if (!xwl_seat->focus_window)
+            continue;
+        if (xwl_seat->focus_window->window == window)
+            xwl_seat->focus_window = NULL;
+    }
+
+    screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
+    ret = (*screen->UnrealizeWindow) (window);
+    xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
+    screen->UnrealizeWindow = xwl_unrealize_window;
+
+    xwl_window =
+        dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+    if (!xwl_window)
+        return ret;
+
+    wl_surface_destroy(xwl_window->surface);
+    if (RegionNotEmpty(DamageRegion(xwl_window->damage)))
+        xorg_list_del(&xwl_window->link_damage);
+    DamageUnregister(xwl_window->damage);
+    DamageDestroy(xwl_window->damage);
+    free(xwl_window);
+    dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
+
+    return ret;
+}
+
+static Bool
+xwl_save_screen(ScreenPtr pScreen, int on)
+{
+    return TRUE;
+}
+
+static void
+xwl_screen_post_damage(struct xwl_screen *xwl_screen)
+{
+    struct xwl_window *xwl_window;
+    RegionPtr region;
+    BoxPtr box;
+    int count, i;
+    struct wl_buffer *buffer;
+    PixmapPtr pixmap;
+
+    xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list,
+                             link_damage) {
+        region = DamageRegion(xwl_window->damage);
+        count = RegionNumRects(region);
+
+        pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
+
+        buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+        wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+        for (i = 0; i < count; i++) {
+            box = &RegionRects(region)[i];
+            wl_surface_damage(xwl_window->surface,
+                              box->x1, box->y1,
+                              box->x2 - box->x1, box->y2 - box->y1);
+        }
+        wl_surface_commit(xwl_window->surface);
+        DamageEmpty(xwl_window->damage);
+    }
+
+    xorg_list_init(&xwl_screen->damage_window_list);
+}
+
+static void
+registry_global(void *data, struct wl_registry *registry, uint32_t id,
+                const char *interface, uint32_t version)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    if (strcmp(interface, "wl_compositor") == 0) {
+        xwl_screen->compositor =
+            wl_registry_bind(registry, id, &wl_compositor_interface, 1);
+    }
+    else if (strcmp(interface, "wl_shm") == 0) {
+        xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
+    }
+    else if (strcmp(interface, "wl_shell") == 0) {
+        xwl_screen->shell =
+            wl_registry_bind(registry, id, &wl_shell_interface, 1);
+    }
+    else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
+        xwl_output_create(xwl_screen, id);
+        xwl_screen->expecting_event++;
+    }
+}
+
+static void
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+    /* Nothing to do here, wl_compositor and wl_shm should not be removed */
+}
+
+static const struct wl_registry_listener registry_listener = {
+    registry_global,
+    global_remove
+};
+
+static void
+wakeup_handler(void *data, int err, void *read_mask)
+{
+    struct xwl_screen *xwl_screen = data;
+    int ret;
+
+    if (err < 0)
+        return;
+
+    if (!FD_ISSET(xwl_screen->wayland_fd, (fd_set *) read_mask))
+        return;
+
+    ret = wl_display_read_events(xwl_screen->display);
+    if (ret == -1)
+        FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+
+    xwl_screen->prepare_read = 0;
+
+    ret = wl_display_dispatch_pending(xwl_screen->display);
+    if (ret == -1)
+        FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+}
+
+static void
+block_handler(void *data, struct timeval **tv, void *read_mask)
+{
+    struct xwl_screen *xwl_screen = data;
+    int ret;
+
+    xwl_screen_post_damage(xwl_screen);
+
+    while (xwl_screen->prepare_read == 0 &&
+           wl_display_prepare_read(xwl_screen->display) == -1) {
+        ret = wl_display_dispatch_pending(xwl_screen->display);
+        if (ret == -1)
+            FatalError("failed to dispatch Wayland events: %s\n",
+                       strerror(errno));
+    }
+
+    xwl_screen->prepare_read = 1;
+
+    ret = wl_display_flush(xwl_screen->display);
+    if (ret == -1)
+        FatalError("failed to write to XWayland fd: %s\n", strerror(errno));
+}
+
+static CARD32
+add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
+{
+    struct xwl_screen *xwl_screen = arg;
+
+    if (!AddClientOnOpenFD(xwl_screen->wm_fd))
+        FatalError("Failed to add wm client\n");
+
+    TimerFree(timer);
+
+    return 0;
+}
+
+static void
+listen_on_fds(struct xwl_screen *xwl_screen)
+{
+    int i;
+
+    for (i = 0; i < xwl_screen->listen_fd_count; i++)
+        ListenOnOpenFD(xwl_screen->listen_fds[i], TRUE);
+}
+
+static void
+wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
+{
+    SelectionInfoRec *info = arg;
+    struct xwl_screen *xwl_screen = data;
+    static const char atom_name[] = "WM_S0";
+    static Atom atom_wm_s0;
+
+    if (atom_wm_s0 == None)
+        atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE);
+    if (info->selection->selection != atom_wm_s0 ||
+        info->kind != SelectionSetOwner)
+        return;
+
+    listen_on_fds(xwl_screen);
+
+    DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
+}
+
+static Bool
+xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
+{
+    struct xwl_screen *xwl_screen;
+    Pixel red_mask, blue_mask, green_mask;
+    int ret, bpc, green_bpc, i;
+
+    xwl_screen = calloc(sizeof *xwl_screen, 1);
+    xwl_screen->wm_fd = -1;
+    if (xwl_screen == NULL)
+        return FALSE;
+
+    if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
+        return FALSE;
+    if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
+        return FALSE;
+    if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
+        return FALSE;
+
+    dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
+    xwl_screen->screen = pScreen;
+
+    for (i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-rootless") == 0) {
+            xwl_screen->rootless = 1;
+        }
+        else if (strcmp(argv[i], "-wm") == 0) {
+            xwl_screen->wm_fd = atoi(argv[i + 1]);
+            i++;
+            TimerSet(NULL, 0, 1, add_client_fd, xwl_screen);
+        }
+        else if (strcmp(argv[i], "-listen") == 0) {
+            if (xwl_screen->listen_fd_count ==
+                ARRAY_SIZE(xwl_screen->listen_fds))
+                FatalError("Too many -listen arguments given, max is %ld\n",
+                           ARRAY_SIZE(xwl_screen->listen_fds));
+
+            xwl_screen->listen_fds[xwl_screen->listen_fd_count++] =
+                atoi(argv[i + 1]);
+            i++;
+        }
+    }
+
+    if (xwl_screen->listen_fd_count > 0) {
+        if (xwl_screen->wm_fd >= 0)
+            AddCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
+        else
+            listen_on_fds(xwl_screen);
+    }
+
+    xorg_list_init(&xwl_screen->output_list);
+    xorg_list_init(&xwl_screen->seat_list);
+    xorg_list_init(&xwl_screen->damage_window_list);
+    xwl_screen->depth = 24;
+
+    xwl_screen->display = wl_display_connect(NULL);
+    if (xwl_screen->display == NULL) {
+        ErrorF("could not connect to wayland server\n");
+        return FALSE;
+    }
+
+    if (!xwl_screen_init_output(xwl_screen))
+        return FALSE;
+
+    xwl_screen->expecting_event = 0;
+    xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
+    wl_registry_add_listener(xwl_screen->registry,
+                             &registry_listener, xwl_screen);
+    ret = wl_display_roundtrip(xwl_screen->display);
+    if (ret == -1) {
+        ErrorF("could not connect to wayland server\n");
+        return FALSE;
+    }
+
+    while (xwl_screen->expecting_event > 0)
+        wl_display_roundtrip(xwl_screen->display);
+
+    bpc = xwl_screen->depth / 3;
+    green_bpc = xwl_screen->depth - 2 * bpc;
+    blue_mask = (1 << bpc) - 1;
+    green_mask = ((1 << green_bpc) - 1) << bpc;
+    red_mask = blue_mask << (green_bpc + bpc);
+
+    miSetVisualTypesAndMasks(xwl_screen->depth,
+                             ((1 << TrueColor) | (1 << DirectColor)),
+                             green_bpc, TrueColor,
+                             red_mask, green_mask, blue_mask);
+
+    miSetPixmapDepths();
+
+    ret = fbScreenInit(pScreen, NULL,
+                       xwl_screen->width, xwl_screen->height,
+                       96, 96, 0,
+                       BitsPerPixel(xwl_screen->depth));
+    if (!ret)
+        return FALSE;
+
+    fbPictureInit(pScreen, 0, 0);
+
+    if (!miSyncShmScreenInit(pScreen))
+        return FALSE;
+
+    xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
+    AddGeneralSocket(xwl_screen->wayland_fd);
+    RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
+
+    pScreen->SaveScreen = xwl_save_screen;
+
+    pScreen->blackPixel = 0;
+    pScreen->whitePixel = 1;
+
+    ret = fbCreateDefColormap(pScreen);
+
+    if (!xwl_screen_init_cursor(xwl_screen))
+        return FALSE;
+
+    xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
+    pScreen->CreatePixmap = xwl_shm_create_pixmap;
+    pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
+
+    xwl_screen->RealizeWindow = pScreen->RealizeWindow;
+    pScreen->RealizeWindow = xwl_realize_window;
+
+    xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
+    pScreen->UnrealizeWindow = xwl_unrealize_window;
+
+    xwl_screen->CloseScreen = pScreen->CloseScreen;
+    pScreen->CloseScreen = xwl_close_screen;
+
+    return ret;
+}
+
+static void _X_ATTRIBUTE_PRINTF(1, 0)
+xwl_log_handler(const char *format, va_list args)
+{
+    char msg[256];
+
+    vsnprintf(msg, sizeof msg, format, args);
+    FatalError("%s", msg);
+}
+
+static const ExtensionModule glx_extension[] = {
+    { GlxExtensionInit, "GLX", &noGlxExtension },
+};
+
+void
+InitOutput(ScreenInfo * screen_info, int argc, char **argv)
+{
+    int depths[] = { 1, 4, 8, 15, 16, 24, 32 };
+    int bpp[] =    { 1, 8, 8, 16, 16, 32, 32 };
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(depths); i++) {
+        screen_info->formats[i].depth = depths[i];
+        screen_info->formats[i].bitsPerPixel = bpp[i];
+        screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD;
+    }
+
+    screen_info->imageByteOrder = IMAGE_BYTE_ORDER;
+    screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+    screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+    screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
+    screen_info->numPixmapFormats = ARRAY_SIZE(depths);
+
+    LoadExtensionList(glx_extension, ARRAY_SIZE(glx_extension), FALSE);
+
+    /* Cast away warning from missing printf annotation for
+     * wl_log_func_t.  Wayland 1.5 will have the annotation, so we can
+     * remove the cast and require that when it's released. */
+    wl_log_set_handler_client((void *) xwl_log_handler);
+
+    if (AddScreen(xwl_screen_init, argc, argv) == -1) {
+        FatalError("Couldn't add screen\n");
+    }
+}
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
new file mode 100644
index 0000000..8157e71
--- /dev/null
+++ b/hw/xwayland/xwayland.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef XWAYLAND_H
+#define XWAYLAND_H
+
+#include <dix-config.h>
+#include <xorg-server.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <wayland-client.h>
+
+#include <X11/X.h>
+
+#include <fb.h>
+#include <input.h>
+#include <dix.h>
+#include <randrstr.h>
+#include <exevents.h>
+
+struct xwl_screen {
+    int width;
+    int height;
+    int depth;
+    ScreenPtr screen;
+    WindowPtr pointer_limbo_window;
+    int expecting_event;
+
+    int wm_fd;
+    int listen_fds[5];
+    int listen_fd_count;
+    int rootless;
+
+    CreateScreenResourcesProcPtr CreateScreenResources;
+    CloseScreenProcPtr CloseScreen;
+    CreateWindowProcPtr CreateWindow;
+    DestroyWindowProcPtr DestroyWindow;
+    RealizeWindowProcPtr RealizeWindow;
+    UnrealizeWindowProcPtr UnrealizeWindow;
+    XYToWindowProcPtr XYToWindow;
+
+    struct xorg_list output_list;
+    struct xorg_list seat_list;
+    struct xorg_list damage_window_list;
+
+    int wayland_fd;
+    struct wl_display *display;
+    struct wl_registry *registry;
+    struct wl_registry *input_registry;
+    struct wl_compositor *compositor;
+    struct wl_shm *shm;
+    struct wl_shell *shell;
+
+    uint32_t serial;
+
+#define XWL_FORMAT_ARGB8888 (1 << 0)
+#define XWL_FORMAT_XRGB8888 (1 << 1)
+#define XWL_FORMAT_RGB565   (1 << 2)
+
+    int prepare_read;
+};
+
+struct xwl_window {
+    struct xwl_screen *xwl_screen;
+    struct wl_surface *surface;
+    struct wl_shell_surface *shell_surface;
+    WindowPtr window;
+    DamagePtr damage;
+    struct xorg_list link_damage;
+};
+
+#define MODIFIER_META 0x01
+
+struct xwl_seat {
+    DeviceIntPtr pointer;
+    DeviceIntPtr keyboard;
+    struct xwl_screen *xwl_screen;
+    struct wl_seat *seat;
+    struct wl_pointer *wl_pointer;
+    struct wl_keyboard *wl_keyboard;
+    struct wl_array keys;
+    struct wl_surface *cursor;
+    struct xwl_window *focus_window;
+    uint32_t id;
+    uint32_t pointer_enter_serial;
+    struct xorg_list link;
+    CursorPtr x_cursor;
+
+    wl_fixed_t horizontal_scroll;
+    wl_fixed_t vertical_scroll;
+    uint32_t scroll_time;
+
+    size_t keymap_size;
+    char *keymap;
+    struct wl_surface *keyboard_focus;
+};
+
+struct xwl_output {
+    struct xorg_list link;
+    struct wl_output *output;
+    struct xwl_screen *xwl_screen;
+    RROutputPtr randr_output;
+    RRCrtcPtr randr_crtc;
+    int32_t x, y, width, height;
+    Rotation rotation;
+};
+
+struct xwl_pixmap;
+
+Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
+
+struct xwl_screen *xwl_screen_get(ScreenPtr screen);
+
+void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
+
+void xwl_seat_destroy(struct xwl_seat *xwl_seat);
+
+Bool xwl_screen_init_output(struct xwl_screen *xwl_screen);
+
+struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen,
+                                     uint32_t id);
+
+void xwl_output_destroy(struct xwl_output *xwl_output);
+
+RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
+                       float VRefresh, Bool Reduced, Bool Interlaced);
+
+void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap);
+struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap);
+
+
+Bool xwl_shm_create_screen_resources(ScreenPtr screen);
+PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height,
+                                int depth, unsigned int hint);
+Bool xwl_shm_destroy_pixmap(PixmapPtr pixmap);
+struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
+
+
+#endif
commit 3c34dd3603989c0365654ca1b6809395c7f3b169
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:48 2014 -0700

    glamor: Add glamor_program based poly_text and image_text
    
    Accelerates text painting with GPU-based geometry computation and stippling
    
    v2: Simplify get_glyphs, expand single character variable names to
        more descriptive ones. (Markus Wick)
    v3: Rebase against the glamor_prepare_* un-renaming (changes by anholt).
    
    Improves x11perf -f8text by 417.908% +/- 11.0144% (n=10)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index dccd923..4d0cc81 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -12,6 +12,7 @@ libglamor_la_SOURCES = \
 	glamor_core.c \
 	glamor_debug.h \
 	glamor_fill.c \
+	glamor_font.c \
 	glamor_glx.c \
 	glamor_glyphs.c \
 	glamor_polylines.c \
@@ -22,6 +23,7 @@ libglamor_la_SOURCES = \
 	glamor_program.c \
 	glamor_rects.c \
 	glamor_spans.c \
+	glamor_text.c \
 	glamor_transfer.c \
 	glamor_transfer.h \
 	glamor_transform.c \
diff --git a/glamor/glamor.c b/glamor/glamor.c
index d7192c1..59548b7 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -424,6 +424,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         screen->CreateScreenResources;
     screen->CreateScreenResources = glamor_create_screen_resources;
 
+    if (!glamor_font_init(screen))
+        goto fail;
+
     if (flags & GLAMOR_USE_SCREEN) {
         if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler,
                                             _glamor_wakeup_handler,
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 2ff0409..5d988da 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -434,6 +434,20 @@ extern _X_EXPORT Bool glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC,
 extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
                                            int mode, int n, DDXPointPtr points);
 
+extern _X_EXPORT Bool glamor_poly_text8_nf(DrawablePtr drawable, GCPtr gc,
+                                           int x, int y, int count, char *chars, int *final_pos);
+
+extern _X_EXPORT Bool glamor_poly_text16_nf(DrawablePtr drawable, GCPtr gc,
+                                            int x, int y, int count, unsigned short *chars, int *final_pos);
+
+extern _X_EXPORT Bool glamor_image_text8_nf(DrawablePtr drawable, GCPtr gc,
+                                            int x, int y, int count, char *chars);
+
+extern _X_EXPORT Bool glamor_image_text16_nf(DrawablePtr drawable, GCPtr gc,
+                                             int x, int y, int count, unsigned short *chars);
+
+#define HAS_GLAMOR_TEXT 1
+
 #ifdef GLAMOR_FOR_XORG
 extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen,
                                                     int num_texture_ports);
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index cdf41ec..7b1615d 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -426,10 +426,10 @@ GCOps glamor_gc_ops = {
     .FillPolygon = miFillPolygon,
     .PolyFillRect = glamor_poly_fill_rect,
     .PolyFillArc = miPolyFillArc,
-    .PolyText8 = miPolyText8,
-    .PolyText16 = miPolyText16,
-    .ImageText8 = miImageText8,
-    .ImageText16 = miImageText16,
+    .PolyText8 = glamor_poly_text8,
+    .PolyText16 = glamor_poly_text16,
+    .ImageText8 = glamor_image_text8,
+    .ImageText16 = glamor_image_text16,
     .ImageGlyphBlt = miImageGlyphBlt,
     .PolyGlyphBlt = glamor_poly_glyph_blt,
     .PushPixels = glamor_push_pixels,
diff --git a/glamor/glamor_font.c b/glamor/glamor_font.c
new file mode 100644
index 0000000..47dfe2a
--- /dev/null
+++ b/glamor/glamor_font.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_font.h"
+#include <dixfontstr.h>
+
+static int glamor_font_generation;
+static int glamor_font_private_index;
+static int glamor_font_screen_count;
+
+glamor_font_t *
+glamor_font_get(ScreenPtr screen, FontPtr font)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_font_t       *privates;
+    glamor_font_t       *glamor_font;
+    int                 overall_width, overall_height;
+    int                 num_rows;
+    int                 num_cols;
+    int                 glyph_width_pixels;
+    int                 glyph_width_bytes;
+    int                 glyph_height;
+    int                 row, col;
+    unsigned char       c[2];
+    CharInfoPtr         glyph;
+    unsigned long       count;
+
+
+    privates = FontGetPrivate(font, glamor_font_private_index);
+    if (!privates) {
+        privates = calloc(glamor_font_screen_count, sizeof (glamor_font_t));
+        if (!privates)
+            return NULL;
+        FontSetPrivate(font, glamor_font_private_index, privates);
+    }
+
+    glamor_font = &privates[screen->myNum];
+
+    if (glamor_font->realized)
+        return glamor_font;
+
+    glamor_font->realized = TRUE;
+
+    /* Figure out how many glyphs are in the font */
+    num_cols = font->info.lastCol - font->info.firstCol + 1;
+    num_rows = font->info.lastRow - font->info.firstRow + 1;
+
+    /* Figure out the size of each glyph */
+    glyph_width_pixels = font->info.maxbounds.rightSideBearing - font->info.minbounds.leftSideBearing;
+    glyph_height = font->info.maxbounds.ascent + font->info.maxbounds.descent;
+
+    glyph_width_bytes = (glyph_width_pixels + 7) >> 3;
+
+    glamor_font->glyph_width_pixels = glyph_width_pixels;
+    glamor_font->glyph_width_bytes = glyph_width_bytes;
+    glamor_font->glyph_height = glyph_height;
+
+    overall_width = glyph_width_bytes * num_cols;
+    overall_height = glyph_height * num_rows;
+
+    /* Check whether the font has a default character */
+    c[0] = font->info.lastRow + 1;
+    c[1] = font->info.lastCol + 1;
+    (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph);
+
+    glamor_font->default_char = count ? glyph : NULL;
+    glamor_font->default_row = font->info.defaultCh >> 8;
+    glamor_font->default_col = font->info.defaultCh;
+
+    glamor_priv = glamor_get_screen_private(screen);
+    glamor_get_context(glamor_priv);
+
+    glGenTextures(1, &glamor_font->texture_id);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    /* Allocate storage */
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, overall_width, overall_height,
+                 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+    /* Paint all of the glyphs */
+    for (row = 0; row < num_rows; row++) {
+        for (col = 0; col < num_cols; col++) {
+            c[0] = row + font->info.firstRow;
+            c[1] = col + font->info.firstCol;
+
+            (*font->get_glyphs)(font, 1, c, TwoD16Bit, &count, &glyph);
+
+            if (count)
+                glTexSubImage2D(GL_TEXTURE_2D, 0, col * glyph_width_bytes, row * glyph_height,
+                                GLYPHWIDTHBYTES(glyph), GLYPHHEIGHTPIXELS(glyph),
+                                GL_RED_INTEGER, GL_UNSIGNED_BYTE, glyph->bits);
+        }
+    }
+
+    glamor_put_context(glamor_priv);
+
+    return glamor_font;
+}
+
+static Bool
+glamor_realize_font(ScreenPtr screen, FontPtr font)
+{
+    return TRUE;
+}
+
+static Bool
+glamor_unrealize_font(ScreenPtr screen, FontPtr font)
+{
+    glamor_screen_private       *glamor_priv;
+    glamor_font_t               *privates = FontGetPrivate(font, glamor_font_private_index);
+    glamor_font_t               *glamor_font;
+    int                         s;
+
+    if (!privates)
+        return TRUE;
+
+    glamor_font = &privates[screen->myNum];
+
+    if (!glamor_font->realized)
+        return TRUE;
+
+    /* Unrealize the font, freeing the allocated texture */
+    glamor_font->realized = FALSE;
+
+    glamor_priv = glamor_get_screen_private(screen);
+    glamor_get_context(glamor_priv);
+    glDeleteTextures(1, &glamor_font->texture_id);
+    glamor_put_context(glamor_priv);
+
+    /* Check to see if all of the screens are  done with this font
+     * and free the private when that happens
+     */
+    for (s = 0; s < glamor_font_screen_count; s++)
+        if (privates[s].realized)
+            return TRUE;
+
+    free(privates);
+    FontSetPrivate(font, glamor_font_private_index, NULL);
+    return TRUE;
+}
+
+Bool
+glamor_font_init(ScreenPtr screen)
+{
+    if (glamor_font_generation != serverGeneration) {
+        glamor_font_private_index = AllocateFontPrivateIndex();
+        if (glamor_font_private_index == -1)
+            return FALSE;
+        glamor_font_screen_count = 0;
+        glamor_font_generation = serverGeneration;
+    }
+
+    if (screen->myNum >= glamor_font_screen_count)
+        glamor_font_screen_count = screen->myNum + 1;
+
+    screen->RealizeFont = glamor_realize_font;
+    screen->UnrealizeFont = glamor_unrealize_font;
+    return TRUE;
+}
diff --git a/glamor/glamor_font.h b/glamor/glamor_font.h
new file mode 100644
index 0000000..36d2062
--- /dev/null
+++ b/glamor/glamor_font.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _GLAMOR_FONT_H_
+#define _GLAMOR_FONT_H_
+
+typedef struct {
+    Bool        realized;
+    CharInfoPtr default_char;
+    CARD8       default_row;
+    CARD8       default_col;
+
+    GLuint      texture_id;
+
+    CARD16      glyph_width_bytes;
+    CARD16      glyph_width_pixels;
+    CARD16      glyph_height;
+
+} glamor_font_t;
+
+glamor_font_t *
+glamor_font_get(ScreenPtr screen, FontPtr font);
+
+Bool
+glamor_font_init(ScreenPtr screen);
+
+void
+glamor_fini_glyph_shader(ScreenPtr screen);
+
+#endif /* _GLAMOR_FONT_H_ */
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 2a8cae1..47f9efe 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -233,6 +233,11 @@ typedef struct glamor_screen_private {
     /* glamor glyphblt shaders */
     glamor_program_fill poly_glyph_blt_progs;
 
+    /* glamor text shaders */
+    glamor_program_fill poly_text_progs;
+    glamor_program      te_text_prog;
+    glamor_program      image_text_prog;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -959,6 +964,19 @@ RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
                             int dstx, int dsty,
                             unsigned long bitPlane);
 
+/* glamor_text.c */
+int glamor_poly_text8(DrawablePtr pDrawable, GCPtr pGC,
+                      int x, int y, int count, char *chars);
+
+int glamor_poly_text16(DrawablePtr pDrawable, GCPtr pGC,
+                       int x, int y, int count, unsigned short *chars);
+
+void glamor_image_text8(DrawablePtr pDrawable, GCPtr pGC,
+                        int x, int y, int count, char *chars);
+
+void glamor_image_text16(DrawablePtr pDrawable, GCPtr pGC,
+                         int x, int y, int count, unsigned short *chars);
+
 /* glamor_spans.c */
 void
 glamor_fill_spans(DrawablePtr drawable,
@@ -1051,4 +1069,6 @@ void glamor_fini_xv_shader(ScreenPtr screen);
 //#define GLYPHS_NO_EDEGEMAP_OVERLAP_CHECK
 #define GLYPHS_EDEGE_OVERLAP_LOOSE_CHECK
 
+#include "glamor_font.h"
+
 #endif                          /* GLAMOR_PRIV_H */
diff --git a/glamor/glamor_text.c b/glamor/glamor_text.c
new file mode 100644
index 0000000..0e4b74c
--- /dev/null
+++ b/glamor/glamor_text.c
@@ -0,0 +1,526 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include <dixfontstr.h>
+#include "glamor_transform.h"
+
+/*
+ * Fill in the array of charinfo pointers for the provided characters. For
+ * missing characters, place a NULL in the array so that the charinfo array
+ * aligns exactly with chars
+ */
+
+static void
+glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font,
+                  int count, char *chars, Bool sixteen, CharInfoPtr *charinfo)
+{
+    unsigned long nglyphs;
+    FontEncoding encoding;
+    int char_step;
+
+    if (sixteen) {
+        char_step = 2;
+        if (FONTLASTROW(font) == 0)
+            encoding = Linear16Bit;
+        else
+            encoding = TwoD16Bit;
+    } else {
+        char_step = 1;
+        encoding = Linear8Bit;
+    }
+
+    /* If the font has a default character, then we don't have to
+     * worry about missing glyphs, so just get the whole string all at
+     * once. Otherwise, we have to fetch chars one at a time to notice
+     * missing ones.
+     */
+    if (glamor_font->default_char) {
+        GetGlyphs(font, (unsigned long) count, (unsigned char *) chars,
+                  encoding, &nglyphs, charinfo);
+    } else {
+        int c;
+        for (c = 0; c < count; c++) {
+            GetGlyphs(font, 1, (unsigned char *) chars,
+                      encoding, &nglyphs, &charinfo[c]);
+            if (!nglyphs)
+                charinfo[c] = NULL;
+            chars += char_step;
+        }
+    }
+}
+
+/*
+ * Construct quads for the provided list of characters and draw them
+ */
+
+static int
+glamor_text(DrawablePtr drawable, GCPtr gc,
+            glamor_font_t *glamor_font,
+            glamor_program *prog,
+            int x, int y,
+            int count, char *s_chars, CharInfoPtr *charinfo,
+            Bool sixteen)
+{
+    unsigned char *chars = (unsigned char *) s_chars;
+    FontPtr font = gc->font;
+    int off_x, off_y;
+    int c;
+    int nglyph;
+    GLshort *v;
+    char *vbo_offset;
+    CharInfoPtr ci;
+    int firstRow = font->info.firstRow;
+    int firstCol = font->info.firstCol;
+    int glyph_spacing_x = glamor_font->glyph_width_bytes * 8;
+    int glyph_spacing_y = glamor_font->glyph_height;
+    int box_x, box_y;
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    /* Set the font as texture 1 */
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id);
+    glUniform1i(prog->font_uniform, 1);
+
+    /* Set up the vertex buffers for the font and destination */
+
+    v = glamor_get_vbo_space(drawable->pScreen, count * (6 * sizeof (GLshort)), &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE,
+                          6 * sizeof (GLshort), vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE,
+                          6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort));
+
+    /* Set the vertex coordinates */
+    nglyph = 0;
+
+    for (c = 0; c < count; c++) {
+        if ((ci = *charinfo++)) {
+            int     x1 = x + ci->metrics.leftSideBearing;
+            int     y1 = y - ci->metrics.ascent;
+            int     width = GLYPHWIDTHPIXELS(ci);
+            int     height = GLYPHHEIGHTPIXELS(ci);
+            int     tx, ty = 0;
+            int     row = 0, col;
+
+            x += ci->metrics.characterWidth;
+
+            if (sixteen) {
+                if (ci == glamor_font->default_char) {
+                    row = glamor_font->default_row;
+                    col = glamor_font->default_col;
+                } else {
+                    row = chars[0];
+                    col = chars[1];
+                }
+                if (FONTLASTROW(font) != 0)
+                    ty = (row - firstRow) * glyph_spacing_y;
+                else
+                    col += row << 8;
+            } else {
+                if (ci == glamor_font->default_char)
+                    col = glamor_font->default_col;
+                else
+                    col = chars[0];
+            }
+
+            tx = (col - firstCol) * glyph_spacing_x;
+
+            v[ 0] = x1;
+            v[ 1] = y1;
+            v[ 2] = width;
+            v[ 3] = height;
+            v[ 4] = tx;
+            v[ 5] = ty;
+
+            v += 6;
+            nglyph++;
+        }
+        chars += 1 + sixteen;
+    }
+    glamor_put_vbo_space(drawable->pScreen);
+
+    if (nglyph != 0) {
+
+        glEnable(GL_SCISSOR_TEST);
+
+        glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+            BoxPtr box = RegionRects(gc->pCompositeClip);
+            int nbox = RegionNumRects(gc->pCompositeClip);
+
+            glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y);
+
+            /* Run over the clip list, drawing the glyphs
+             * in each box
+             */
+
+            while (nbox--) {
+                glScissor(box->x1 + off_x,
+                          box->y1 + off_y,
+                          box->x2 - box->x1,
+                          box->y2 - box->y1);
+                box++;
+                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph);
+            }
+        }
+        glDisable(GL_SCISSOR_TEST);
+    }
+
+    glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisable(GL_COLOR_LOGIC_OP);
+
+    return x;
+}
+
+static const char vs_vars_text[] =
+    "attribute vec4 primitive;\n"
+    "attribute vec2 source;\n"
+    "varying vec2 glyph_pos;\n";
+
+static const char vs_exec_text[] =
+    "       vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
+    GLAMOR_POS(gl_Position, (primitive.xy + pos))
+    "       glyph_pos = source + pos;\n";
+
+static const char fs_vars_text[] =
+    "varying vec2 glyph_pos;\n";
+
+static const char fs_exec_text[] =
+    "       ivec2 itile_texture = ivec2(glyph_pos);\n"
+    "       uint x = uint(itile_texture.x & 7);\n"
+    "       itile_texture.x >>= 3;\n"
+    "       uint texel = texelFetch(font, itile_texture, 0).x;\n"
+    "       uint bit = (texel >> x) & uint(1);\n"
+    "       if (bit == uint(0))\n"
+    "               discard;\n";
+
+static const char fs_exec_te[] =
+    "       ivec2 itile_texture = ivec2(glyph_pos);\n"
+    "       uint x = uint(itile_texture.x & 7);\n"
+    "       itile_texture.x >>= 3;\n"
+    "       uint texel = texelFetch(font, itile_texture, 0).x;\n"
+    "       uint bit = (texel >> x) & uint(1);\n"
+    "       if (bit == uint(0))\n"
+    "               gl_FragColor = bg;\n"
+    "       else\n"
+    "               gl_FragColor = fg;\n";
+
+static const glamor_facet glamor_facet_poly_text = {
+    .name = "poly_text",
+    .version = 130,
+    .vs_vars = vs_vars_text,
+    .vs_exec = vs_exec_text,
+    .fs_vars = fs_vars_text,
+    .fs_exec = fs_exec_text,
+    .source_name = "source",
+    .locations = glamor_program_location_font,
+};
+
+static Bool
+glamor_poly_text(DrawablePtr drawable, GCPtr gc,
+                 int x, int y, int count, char *chars, Bool sixteen, int *final_pos)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_program *prog;
+    glamor_pixmap_private *pixmap_priv;
+    glamor_font_t *glamor_font;
+    CharInfoPtr charinfo[255];  /* encoding only has 1 byte for count */
+
+    glamor_font = glamor_font_get(drawable->pScreen, gc->font);
+    if (!glamor_font)
+        goto bail;
+
+    glamor_get_glyphs(gc->font, glamor_font, count, chars, sixteen, charinfo);
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    glamor_get_context(glamor_priv);
+
+    prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_text_progs, &glamor_facet_poly_text);
+
+    if (!prog)
+        goto bail_ctx;
+
+    x = glamor_text(drawable, gc, glamor_font, prog,
+                    x, y, count, chars, charinfo, sixteen);
+
+    glDisable(GL_COLOR_LOGIC_OP);
+
+    glamor_put_context(glamor_priv);
+
+    glamor_priv->state = RENDER_STATE;
+    glamor_priv->render_idle_cnt = 0;
+
+    *final_pos = x;
+    return TRUE;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    glamor_put_context(glamor_priv);
+bail:
+    return FALSE;
+}
+
+Bool
+glamor_poly_text8_nf(DrawablePtr drawable, GCPtr gc,
+                     int x, int y, int count, char *chars, int *final_pos)
+{
+    if (glamor_poly_text(drawable, gc, x, y, count, chars, FALSE, final_pos))
+        return TRUE;
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+    *final_pos = miPolyText8(drawable, gc, x, y, count, chars);
+    return TRUE;
+}
+
+int
+glamor_poly_text8(DrawablePtr drawable, GCPtr gc,
+                   int x, int y, int count, char *chars)
+{
+    int final_pos;
+
+    if (glamor_poly_text(drawable, gc, x, y, count, chars, FALSE, &final_pos))
+        return final_pos;
+    return miPolyText8(drawable, gc, x, y, count, chars);
+}
+
+Bool
+glamor_poly_text16_nf(DrawablePtr drawable, GCPtr gc,
+                      int x, int y, int count, unsigned short *chars, int *final_pos)
+{
+    if (glamor_poly_text(drawable, gc, x, y, count, (char *) chars, TRUE, final_pos))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+    *final_pos = miPolyText16(drawable, gc, x, y, count, chars);
+    return TRUE;
+}
+
+int
+glamor_poly_text16(DrawablePtr drawable, GCPtr gc,
+                    int x, int y, int count, unsigned short *chars)
+{
+    int final_pos;
+
+    if (glamor_poly_text(drawable, gc, x, y, count, (char *) chars, TRUE, &final_pos))
+        return final_pos;
+    return miPolyText16(drawable, gc, x, y, count, chars);
+}
+
+/*
+ * Draw image text, which is always solid in copy mode and has the
+ * background cleared while painting the text. For fonts which have
+ * their bitmap metrics exactly equal to the area to clear, we can use
+ * the accelerated version which paints both fg and bg at the same
+ * time. Otherwise, clear the whole area and then paint the glyphs on
+ * top
+ */
+
+static const glamor_facet glamor_facet_image_text = {
+    .name = "image_text",
+    .version = 130,
+    .vs_vars = vs_vars_text,
+    .vs_exec = vs_exec_text,
+    .fs_vars = fs_vars_text,
+    .fs_exec = fs_exec_text,
+    .source_name = "source",
+    .locations = glamor_program_location_font,
+};
+
+static Bool
+use_image_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
+{
+    return glamor_set_solid(pixmap, gc, FALSE, prog->fg_uniform);
+}
+
+static const glamor_facet glamor_facet_image_fill = {
+    .name = "solid",
+    .fs_exec = "       gl_FragColor = fg;\n",
+    .locations = glamor_program_location_fg,
+    .use = use_image_solid,
+};
+
+static Bool
+glamor_te_text_use(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
+{
+    if (!glamor_set_solid(pixmap, gc, FALSE, prog->fg_uniform))
+        return FALSE;
+    glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
+    return TRUE;
+}
+
+static const glamor_facet glamor_facet_te_text = {
+    .name = "te_text",
+    .version = 130,
+    .vs_vars = vs_vars_text,
+    .vs_exec = vs_exec_text,
+    .fs_vars = fs_vars_text,
+    .fs_exec = fs_exec_te,
+    .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_font,
+    .source_name = "source",
+    .use = glamor_te_text_use,
+};
+
+static Bool
+glamor_image_text(DrawablePtr drawable, GCPtr gc,
+                  int x, int y, int count, char *chars,
+                  Bool sixteen)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_program *prog;
+    glamor_pixmap_private *pixmap_priv;
+    glamor_font_t *glamor_font;
+    const glamor_facet *prim_facet;
+    const glamor_facet *fill_facet;
+    CharInfoPtr charinfo[255];  /* encoding only has 1 byte for count */
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        return FALSE;
+
+    glamor_font = glamor_font_get(drawable->pScreen, gc->font);
+    if (!glamor_font)
+        return FALSE;
+
+    glamor_get_glyphs(gc->font, glamor_font, count, chars, sixteen, charinfo);
+
+    glamor_get_context(glamor_priv);
+
+    if (TERMINALFONT(gc->font))
+        prog = &glamor_priv->te_text_prog;
+    else
+        prog = &glamor_priv->image_text_prog;
+
+    if (prog->failed)
+        goto bail;
+
+    if (!prog->prog) {
+        if (TERMINALFONT(gc->font)) {
+            prim_facet = &glamor_facet_te_text;
+            fill_facet = NULL;
+        } else {
+            prim_facet = &glamor_facet_image_text;
+            fill_facet = &glamor_facet_image_fill;
+        }
+
+        if (!glamor_build_program(screen, prog, prim_facet, fill_facet))
+            goto bail;
+    }
+
+    if (!TERMINALFONT(gc->font)) {
+        int width = 0;
+        int c;
+        RegionRec region;
+        BoxRec box;
+        int off_x, off_y;
+
+        /* Check planemask before drawing background to
+         * bail early if it's not OK
+         */
+        if (!glamor_set_planemask(pixmap, gc->planemask))
+            goto bail;
+        for (c = 0; c < count; c++)
+            if (charinfo[c])
+                width += charinfo[c]->metrics.characterWidth;
+
+        glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+        if (width >= 0) {
+            box.x1 = off_x + drawable->x + x;
+            box.x2 = off_x + drawable->x + x + width;
+        } else {
+            box.x1 = off_x + drawable->x + x + width;
+            box.x2 = off_x + drawable->x + x;
+        }
+        box.y1 = off_y + drawable->y + y - gc->font->info.fontAscent;
+        box.y2 = off_y + drawable->y + y + gc->font->info.fontDescent;
+        RegionInit(&region, &box, 1);
+        RegionIntersect(&region, &region, gc->pCompositeClip);
+        glamor_solid_boxes(pixmap, RegionRects(&region), RegionNumRects(&region), gc->bgPixel);
+        RegionUninit(&region);
+    }
+
+    if (!glamor_use_program(pixmap, gc, prog, NULL))
+        goto bail;
+
+    (void) glamor_text(drawable, gc, glamor_font, prog,
+                       x, y, count, chars, charinfo, sixteen);
+
+    glamor_put_context(glamor_priv);
+
+    glamor_priv->state = RENDER_STATE;
+    glamor_priv->render_idle_cnt = 0;
+
+    return TRUE;
+
+bail:
+    glDisable(GL_COLOR_LOGIC_OP);
+    glamor_put_context(glamor_priv);
+    return FALSE;
+}
+
+Bool
+glamor_image_text8_nf(DrawablePtr drawable, GCPtr gc,
+                   int x, int y, int count, char *chars)
+{
+    return glamor_image_text(drawable, gc, x, y, count, chars, FALSE);
+}
+
+void
+glamor_image_text8(DrawablePtr drawable, GCPtr gc,
+                   int x, int y, int count, char *chars)
+{
+    if (!glamor_image_text(drawable, gc, x, y, count, chars, FALSE))
+        miImageText8(drawable, gc, x, y, count, chars);
+}
+
+Bool
+glamor_image_text16_nf(DrawablePtr drawable, GCPtr gc,
+                       int x, int y, int count, unsigned short *chars)
+{
+    return glamor_image_text(drawable, gc, x, y, count, (char *) chars, FALSE);
+}
+
+void
+glamor_image_text16(DrawablePtr drawable, GCPtr gc,
+                    int x, int y, int count, unsigned short *chars)
+{
+    if (!glamor_image_text(drawable, gc, x, y, count, (char *) chars, TRUE))
+        miImageText16(drawable, gc, x, y, count, chars);
+}
commit 5f700c3ac31db52f02f6ef11ea7823a8ce4f6f6f
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:47 2014 -0700

    glamor: Use glamor_program for glamor_glyphblt
    
    This constructs suitable shaders using the glamor_program
    infrastructure for poly glyph blt, and then gets rid of the no-op
    wrapper of miImageGlyphBlt.
    
    Improves x11perf -f8text by 11.6221% +/- 1.04585% (n=10)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 5711be7..cdf41ec 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -430,9 +430,9 @@ GCOps glamor_gc_ops = {
     .PolyText16 = miPolyText16,
     .ImageText8 = miImageText8,
     .ImageText16 = miImageText16,
-    .ImageGlyphBlt = glamor_image_glyph_blt,    //miImageGlyphBlt,
-    .PolyGlyphBlt = glamor_poly_glyph_blt,      //miPolyGlyphBlt,
-    .PushPixels = glamor_push_pixels,   //miPushPixels,
+    .ImageGlyphBlt = miImageGlyphBlt,
+    .PolyGlyphBlt = glamor_poly_glyph_blt,
+    .PushPixels = glamor_push_pixels,
 };
 
 /**
diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index a58cef9..c031747 100644
--- a/glamor/glamor_glyphblt.c
+++ b/glamor/glamor_glyphblt.c
@@ -28,203 +28,156 @@
 
 #include "glamor_priv.h"
 #include <dixfontstr.h>
+#include "glamor_transform.h"
+
+static const glamor_facet glamor_facet_poly_glyph_blt = {
+    .name = "poly_glyph_blt",
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = ("       vec2 pos = vec2(0,0);\n"
+                GLAMOR_POS(gl_Position, primitive)),
+};
 
 static Bool
-glamor_poly_glyph_blt_pixels(DrawablePtr drawable, GCPtr gc,
-                             int x, int y, unsigned int nglyph,
-                             CharInfoPtr *ppci)
+glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
+                         int start_x, int y, unsigned int nglyph,
+                         CharInfoPtr *ppci, void *pglyph_base)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
     glamor_pixmap_private *pixmap_priv;
-    int off_x, off_y;
-    GLfloat xscale, yscale;
-    float color[4];
-    unsigned long fg_pixel = gc->fgPixel;
-    char *vbo_offset;
-    RegionPtr clip;
-    int num_points, max_points;
-    float *points = NULL;
-
-    x += drawable->x;
-    y += drawable->y;
-
-    if (gc->fillStyle != FillSolid) {
-        glamor_fallback("gc fillstyle not solid\n");
-        return FALSE;
-    }
+    glamor_program *prog;
+    RegionPtr clip = gc->pCompositeClip;
+    int box_x, box_y;
 
     pixmap_priv = glamor_get_pixmap_private(pixmap);
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return FALSE;
+        goto bail;
 
     glamor_get_context(glamor_priv);
-    if (!glamor_set_alu(screen, gc->alu)) {
-        if (gc->alu == GXclear)
-            fg_pixel = 0;
-        else {
-            glamor_fallback("unsupported alu %x\n", gc->alu);
-            glamor_put_context(glamor_priv);
-            return FALSE;
-        }
-    }
-
-    if (!glamor_set_planemask(pixmap, gc->planemask)) {
-        glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
-        glamor_put_context(glamor_priv);
-        return FALSE;
-    }
-
-    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
-
-    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
-    pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
-
-    glUseProgram(glamor_priv->solid_prog);
 
-    glamor_get_rgba_from_pixel(fg_pixel,
-                               &color[0], &color[1], &color[2], &color[3],
-                               format_for_pixmap(pixmap));
-    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
-
-    clip = fbGetCompositeClip(gc);
+    prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs,
+                                   &glamor_facet_poly_glyph_blt);
+    if (!prog)
+        goto bail_ctx;
 
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
-    max_points = 500;
-    num_points = 0;
-    while (nglyph--) {
-        CharInfoPtr charinfo = *ppci++;
-        int w = GLYPHWIDTHPIXELS(charinfo);
-        int h = GLYPHHEIGHTPIXELS(charinfo);
-        uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);
-
-        if (w && h) {
-            int glyph_x = x + charinfo->metrics.leftSideBearing;
-            int glyph_y = y - charinfo->metrics.ascent;
-            int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
-            int xx, yy;
-
-            for (yy = 0; yy < h; yy++) {
-                uint8_t *glyph_row = glyphbits + glyph_stride * yy;
-                for (xx = 0; xx < w; xx++) {
-                    int pt_x_i = glyph_x + xx;
-                    int pt_y_i = glyph_y + yy;
-                    float pt_x_f, pt_y_f;
-                    if (!(glyph_row[xx / 8] & (1 << xx % 8)))
-                        continue;
-
-                    if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
-                        continue;
-
-                    if (!num_points) {
-                        points = glamor_get_vbo_space(screen,
-                                                      max_points * 2 * sizeof(float),
-                                                      &vbo_offset);
-
-                        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                              GL_FALSE, 2 * sizeof(float),
-                                              vbo_offset);
-                    }
-
-                    pt_x_f = v_from_x_coord_x(xscale, pt_x_i + off_x + 0.5);
-                    if (glamor_priv->yInverted)
-                        pt_y_f = v_from_x_coord_y_inverted(yscale, pt_y_i + off_y + 0.5);
-                    else
-                        pt_y_f = v_from_x_coord_y(yscale, pt_y_i + off_y + 0.5);
-
-                    points[num_points * 2 + 0] = pt_x_f;
-                    points[num_points * 2 + 1] = pt_y_f;
-                    num_points++;
+    start_x += drawable->x;
+    y += drawable->y;
 
-                    if (num_points == max_points) {
-                        glamor_put_vbo_space(screen);
-                        glDrawArrays(GL_POINTS, 0, num_points);
-                        num_points = 0;
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int x;
+        int n;
+        int num_points, max_points;
+        INT16 *points = NULL;
+        int off_x, off_y;
+        char *vbo_offset;
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y);
+
+        max_points = 500;
+        num_points = 0;
+        x = start_x;
+        for (n = 0; n < nglyph; n++) {
+            CharInfoPtr charinfo = ppci[n];
+            int w = GLYPHWIDTHPIXELS(charinfo);
+            int h = GLYPHHEIGHTPIXELS(charinfo);
+            uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);
+
+            if (w && h) {
+                int glyph_x = x + charinfo->metrics.leftSideBearing;
+                int glyph_y = y - charinfo->metrics.ascent;
+                int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
+                int xx, yy;
+
+                for (yy = 0; yy < h; yy++) {
+                    uint8_t *glyph = glyphbits;
+                    for (xx = 0; xx < w; glyph += ((xx&7) == 7), xx++) {
+                        int pt_x_i = glyph_x + xx;
+                        int pt_y_i = glyph_y + yy;
+
+                        if (!(*glyph & (1 << (xx & 7))))
+                            continue;
+
+                        if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
+                            continue;
+
+                        if (!num_points) {
+                            points = glamor_get_vbo_space(screen,
+                                                          max_points * (2 * sizeof (INT16)),
+                                                          &vbo_offset);
+
+                            glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
+                                                  GL_FALSE, 0, vbo_offset);
+                        }
+
+                        *points++ = pt_x_i;
+                        *points++ = pt_y_i;
+                        num_points++;
+
+                        if (num_points == max_points) {
+                            glamor_put_vbo_space(screen);
+                            glDrawArrays(GL_POINTS, 0, num_points);
+                            num_points = 0;
+                        }
                     }
+                    glyphbits += glyph_stride;
                 }
             }
+            x += charinfo->metrics.characterWidth;
         }
 
-        x += charinfo->metrics.characterWidth;
-    }
-
-    if (num_points) {
-        glamor_put_vbo_space(screen);
-        glDrawArrays(GL_POINTS, 0, num_points);
+        if (num_points) {
+            glamor_put_vbo_space(screen);
+            glDrawArrays(GL_POINTS, 0, num_points);
+        }
     }
 
+    glDisable(GL_COLOR_LOGIC_OP);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     glamor_put_context(glamor_priv);
-
-    return TRUE;
-}
-
-static Bool
-_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
-                        int x, int y, unsigned int nglyph,
-                        CharInfoPtr *ppci, void *pglyphBase, Bool fallback)
-{
-    if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
-        && glamor_ddx_fallback_check_gc(pGC))
-        return FALSE;
-
-    miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
     return TRUE;
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    glamor_put_context(glamor_priv);
+bail:
+    return FALSE;
 }
 
 void
-glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
-                       int x, int y, unsigned int nglyph,
-                       CharInfoPtr *ppci, void *pglyphBase)
+glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc,
+                      int start_x, int y, unsigned int nglyph,
+                      CharInfoPtr *ppci, void *pglyph_base)
 {
-    _glamor_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase,
-                            TRUE);
+    if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
+        return;
+    miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
+                   ppci, pglyph_base);
 }
 
 Bool
-glamor_image_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC,
-                          int x, int y, unsigned int nglyph,
-                          CharInfoPtr *ppci, void *pglyphBase)
-{
-    return _glamor_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci,
-                                   pglyphBase, FALSE);
-}
-
-static Bool
-_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
-                       int x, int y, unsigned int nglyph,
-                       CharInfoPtr *ppci, void *pglyphBase, Bool fallback)
+glamor_poly_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
+                         int start_x, int y, unsigned int nglyph,
+                         CharInfoPtr *ppci, void *pglyph_base)
 {
-    if (glamor_poly_glyph_blt_pixels(pDrawable, pGC, x, y, nglyph, ppci))
+    if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
         return TRUE;
-
-    if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
-        && glamor_ddx_fallback_check_gc(pGC))
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
         return FALSE;
-
-    miPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+    miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
+                   ppci, pglyph_base);
     return TRUE;
 }
 
-void
-glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
-                      int x, int y, unsigned int nglyph,
-                      CharInfoPtr *ppci, void *pglyphBase)
-{
-    _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase,
-                           TRUE);
-}
-
 Bool
-glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC,
-                         int x, int y, unsigned int nglyph,
-                         CharInfoPtr *ppci, void *pglyphBase)
+glamor_image_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
+                          int start_x, int y, unsigned int nglyph,
+                          CharInfoPtr *ppci, void *pglyph_base)
 {
-    return _glamor_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci,
-                                  pglyphBase, FALSE);
+    miImageGlyphBlt(drawable, gc, start_x, y, nglyph, ppci, pglyph_base);
+    return TRUE;
 }
 
 static Bool
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 74bb789..2a8cae1 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -230,6 +230,9 @@ typedef struct glamor_screen_private {
     /* glamor rect shaders */
     glamor_program_fill poly_fill_rect_program;
 
+    /* glamor glyphblt shaders */
+    glamor_program_fill poly_glyph_blt_progs;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
commit 3411e8c538476443cafbb70082ef7457932e4a38
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:46 2014 -0700

    glamor: Add glamor_program based poly_fill_rect
    
    This accelerates poly_fill_rect using GPU-based geometry computation
    
    Improves x11perf -rect100 by 41.5127% +/- 7.63888% (n=10)
    Improves x11perf -rect10 by 3745.72% +/- 94.7503% (n=6)
    
    v2: Rebase on skipping the prepare rewrite for now, and fix the GLSL
        1.20 and GLES2 cases (changes by anholt).
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 4be9f34..dccd923 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -14,13 +14,13 @@ libglamor_la_SOURCES = \
 	glamor_fill.c \
 	glamor_glx.c \
 	glamor_glyphs.c \
-	glamor_polyfillrect.c \
 	glamor_polylines.c \
 	glamor_putimage.c \
 	glamor_segment.c \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_program.c \
+	glamor_rects.c \
 	glamor_spans.c \
 	glamor_transfer.c \
 	glamor_transfer.h \
diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c
deleted file mode 100644
index 1e361a4..0000000
--- a/glamor/glamor_polyfillrect.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * 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 "glamor_priv.h"
-
-/** @file glamor_fillspans.c
- *
- * GC PolyFillRect implementation, taken straight from fb_fill.c
- */
-
-static Bool
-_glamor_poly_fill_rect(DrawablePtr drawable,
-                       GCPtr gc, int nrect, xRectangle *prect, Bool fallback)
-{
-    int fullX1, fullX2, fullY1, fullY2;
-    int xorg, yorg;
-    int n;
-    register BoxPtr pbox;
-    RegionPtr pClip = fbGetCompositeClip(gc);
-    Bool ret = FALSE;
-
-    xorg = drawable->x;
-    yorg = drawable->y;
-
-    while (nrect--) {
-        fullX1 = prect->x + xorg;
-        fullY1 = prect->y + yorg;
-        fullX2 = fullX1 + (int) prect->width;
-        fullY2 = fullY1 + (int) prect->height;
-
-        n = REGION_NUM_RECTS(pClip);
-        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--) {
-            int x1 = fullX1;
-            int x2 = fullX2;
-            int y1 = fullY1;
-            int y2 = fullY2;
-
-            if (pbox->x1 > x1)
-                x1 = pbox->x1;
-            if (pbox->x2 < x2)
-                x2 = pbox->x2;
-            if (pbox->y1 > y1)
-                y1 = pbox->y1;
-            if (pbox->y2 < y2)
-                y2 = pbox->y2;
-
-            pbox++;
-            if (x1 >= x2 || y1 >= y2)
-                continue;
-            if (!glamor_fill(drawable, gc, x1, y1, x2 - x1, y2 - y1, fallback)) {
-                nrect++;
-                goto fail;
-            }
-        }
-        prect++;
-    }
-    ret = TRUE;
-    goto done;
-
- fail:
-
-    if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)
-        && glamor_ddx_fallback_check_gc(gc))
-        goto done;
-
-    glamor_fallback(" to %p (%c)\n",
-                    drawable, glamor_get_drawable_location(drawable));
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access_gc(gc)) {
-        fbPolyFillRect(drawable, gc, nrect, prect);
-    }
-    glamor_finish_access_gc(gc);
-    glamor_finish_access(drawable);
-    ret = TRUE;
-
- done:
-    return ret;
-}
-
-void
-glamor_poly_fill_rect(DrawablePtr drawable,
-                      GCPtr gc, int nrect, xRectangle *prect)
-{
-    _glamor_poly_fill_rect(drawable, gc, nrect, prect, TRUE);
-}
-
-Bool
-glamor_poly_fill_rect_nf(DrawablePtr drawable,
-                         GCPtr gc, int nrect, xRectangle *prect)
-{
-    return _glamor_poly_fill_rect(drawable, gc, nrect, prect, FALSE);
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 430ca59..74bb789 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -227,6 +227,9 @@ typedef struct glamor_screen_private {
     /* glamor spans shaders */
     glamor_program_fill fill_spans_program;
 
+    /* glamor rect shaders */
+    glamor_program_fill poly_fill_rect_program;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -691,10 +694,6 @@ void glamor_glyphs(CARD8 op,
                    INT16 xSrc,
                    INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs);
 
-/* glamor_polyfillrect.c */
-void glamor_poly_fill_rect(DrawablePtr drawable,
-                           GCPtr gc, int nrect, xRectangle *prect);
-
 /* glamor_polylines.c */
 void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
                        DDXPointPtr points);
@@ -971,6 +970,11 @@ void
 glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
                  DDXPointPtr points, int *widths, int numPoints, int sorted);
 
+/* glamor_rects.c */
+void
+glamor_poly_fill_rect(DrawablePtr drawable,
+                      GCPtr gc, int nrect, xRectangle *prect);
+
 /* glamor_glyphblt.c */
 void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
                             int x, int y, unsigned int nglyph,
diff --git a/glamor/glamor_rects.c b/glamor/glamor_rects.c
new file mode 100644
index 0000000..7731ede
--- /dev/null
+++ b/glamor/glamor_rects.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_program.h"
+#include "glamor_transform.h"
+
+static const glamor_facet glamor_facet_polyfillrect_130 = {
+    .name = "poly_fill_rect",
+    .version = 130,
+    .vs_vars = "attribute vec4 primitive;\n",
+    .vs_exec = ("       vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
+                GLAMOR_POS(gl_Position, (primitive.xy + pos))),
+};
+
+static const glamor_facet glamor_facet_polyfillrect_120 = {
+    .name = "poly_fill_rect",
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = ("        vec2 pos = vec2(0,0);\n"
+                GLAMOR_POS(gl_Position, primitive.xy)),
+};
+
+static Bool
+glamor_poly_fill_rect_gl(DrawablePtr drawable,
+                         GCPtr gc, int nrect, xRectangle *prect)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    glamor_program *prog;
+    int off_x, off_y;
+    GLshort *v;
+    char *vbo_offset;
+    int box_x, box_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    glamor_get_context(glamor_priv);
+
+    if (glamor_priv->glsl_version >= 130) {
+        prog = glamor_use_program_fill(pixmap, gc,
+                                       &glamor_priv->poly_fill_rect_program,
+                                       &glamor_facet_polyfillrect_130);
+
+        if (!prog)
+            goto bail_ctx;
+
+        /* Set up the vertex buffers for the points */
+
+        v = glamor_get_vbo_space(drawable->pScreen, nrect * sizeof (xRectangle), &vbo_offset);
+
+        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
+        glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE,
+                              4 * sizeof (short), vbo_offset);
+
+        memcpy(v, prect, nrect * sizeof (xRectangle));
+
+        glamor_put_vbo_space(screen);
+    } else {
+        int n;
+
+        prog = glamor_use_program_fill(pixmap, gc,
+                                       &glamor_priv->poly_fill_rect_program,
+                                       &glamor_facet_polyfillrect_120);
+
+        if (!prog)
+            goto bail_ctx;
+
+        /* Set up the vertex buffers for the points */
+
+        v = glamor_get_vbo_space(drawable->pScreen, nrect * 8 * sizeof (short), &vbo_offset);
+
+        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
+                              2 * sizeof (short), vbo_offset);
+
+        for (n = 0; n < nrect; n++) {
+            v[0] = prect->x;                v[1] = prect->y;
+            v[2] = prect->x;                v[3] = prect->y + prect->height;
+            v[4] = prect->x + prect->width; v[5] = prect->y + prect->height;
+            v[6] = prect->x + prect->width; v[7] = prect->y;
+            prect++;
+            v += 8;
+        }
+
+        glamor_put_vbo_space(screen);
+    }
+
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int nbox = RegionNumRects(gc->pCompositeClip);
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, FALSE, prog->matrix_uniform, &off_x, &off_y);
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            if (glamor_priv->glsl_version >= 130)
+                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect);
+            else {
+                if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+                    glDrawArrays(GL_QUADS, 0, nrect * 4);
+                } else {
+                    int i;
+                    for (i = 0; i < nrect; i++) {
+                        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
+                    }
+                }
+            }
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    if (glamor_priv->glsl_version >= 130)
+        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    glamor_put_context(glamor_priv);
+    return TRUE;
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    glamor_put_context(glamor_priv);
+bail:
+    return FALSE;
+}
+
+static void
+glamor_poly_fill_rect_bail(DrawablePtr drawable,
+                           GCPtr gc, int nrect, xRectangle *prect)
+{
+    glamor_fallback("to %p (%c)\n", drawable,
+                    glamor_get_drawable_location(drawable));
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc)) {
+        fbPolyFillRect(drawable, gc, nrect, prect);
+    }
+    glamor_finish_access_gc(gc);
+    glamor_finish_access(drawable);
+}
+
+void
+glamor_poly_fill_rect(DrawablePtr drawable,
+                      GCPtr gc, int nrect, xRectangle *prect)
+{
+    if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect))
+        return;
+    glamor_poly_fill_rect_bail(drawable, gc, nrect, prect);
+}
+
+Bool
+glamor_poly_fill_rect_nf(DrawablePtr drawable,
+                         GCPtr gc, int nrect, xRectangle *prect)
+{
+    if (glamor_poly_fill_rect_gl(drawable, gc, nrect, prect))
+        return TRUE;
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+    glamor_poly_fill_rect_bail(drawable, gc, nrect, prect);
+    return TRUE;
+}
commit 0a6d31161811c422799d6f065ea2842d42707530
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:45 2014 -0700

    glamor: Add glamor_program based fill/set/get spans
    
    This accelerates spans operations using GPU-based geometry computation
    
    -wellipse500 goes from about 4k/sec before the patch, to ~8k/sec in
    the GLES2 fallback loop, to ~100k/sec in desktop mode.
    
    v2: Rebase on skipping the prepare rewrite for now, and fix the GLSL
        1.20 and GLES2 cases (changes by anholt).
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 3664fd3..4be9f34 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -12,18 +12,16 @@ libglamor_la_SOURCES = \
 	glamor_core.c \
 	glamor_debug.h \
 	glamor_fill.c \
-	glamor_fillspans.c \
-	glamor_getspans.c \
 	glamor_glx.c \
 	glamor_glyphs.c \
 	glamor_polyfillrect.c \
 	glamor_polylines.c \
 	glamor_putimage.c \
-	glamor_setspans.c \
 	glamor_segment.c \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_program.c \
+	glamor_spans.c \
 	glamor_transfer.c \
 	glamor_transfer.h \
 	glamor_transform.c \
diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c
deleted file mode 100644
index 8cbd79f..0000000
--- a/glamor/glamor_fillspans.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright © 1998 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.
- */
-
-/** @file glamor_fillspans.c
- *
- * FillSpans implementation, taken from fb_fillsp.c
- */
-#include "glamor_priv.h"
-
-static Bool
-_glamor_fill_spans(DrawablePtr drawable,
-                   GCPtr gc,
-                   int n, DDXPointPtr points, int *widths, int sorted,
-                   Bool fallback)
-{
-    DDXPointPtr ppt;
-    int nbox;
-    BoxPtr pbox;
-    int x1, x2, y;
-    RegionPtr pClip = fbGetCompositeClip(gc);
-    Bool ret = FALSE;
-
-    if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled)
-        goto fail;
-
-    ppt = points;
-    while (n--) {
-        x1 = ppt->x;
-        y = ppt->y;
-        x2 = x1 + (int) *widths;
-        ppt++;
-        widths++;
-
-        nbox = REGION_NUM_RECTS(pClip);
-        pbox = REGION_RECTS(pClip);
-        while (nbox--) {
-            int real_x1 = x1, real_x2 = x2;
-
-            if (real_x1 < pbox->x1)
-                real_x1 = pbox->x1;
-
-            if (real_x2 > pbox->x2)
-                real_x2 = pbox->x2;
-
-            if (real_x2 > real_x1 && pbox->y1 <= y && pbox->y2 > y) {
-                if (!glamor_fill(drawable, gc, real_x1, y,
-                                 real_x2 - real_x1, 1, fallback))
-                    goto fail;
-            }
-            pbox++;
-        }
-    }
-    ret = TRUE;
-    goto done;
-
- fail:
-    if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)
-        && glamor_ddx_fallback_check_gc(gc)) {
-        goto done;
-    }
-    glamor_fallback("to %p (%c)\n", drawable,
-                    glamor_get_drawable_location(drawable));
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access_gc(gc)) {
-        fbFillSpans(drawable, gc, n, points, widths, sorted);
-    }
-    glamor_finish_access_gc(gc);
-    glamor_finish_access(drawable);
-    ret = TRUE;
-
- done:
-    return ret;
-}
-
-void
-glamor_fill_spans(DrawablePtr drawable,
-                  GCPtr gc, int n, DDXPointPtr points, int *widths, int sorted)
-{
-    _glamor_fill_spans(drawable, gc, n, points, widths, sorted, TRUE);
-}
-
-Bool
-glamor_fill_spans_nf(DrawablePtr drawable,
-                     GCPtr gc,
-                     int n, DDXPointPtr points, int *widths, int sorted)
-{
-    return _glamor_fill_spans(drawable, gc, n, points, widths, sorted, FALSE);
-}
diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c
deleted file mode 100644
index 42df87f..0000000
--- a/glamor/glamor_getspans.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright © 2009 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>
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- *
- */
-
-#include "glamor_priv.h"
-
-static Bool
-_glamor_get_spans(DrawablePtr drawable,
-                  int wmax,
-                  DDXPointPtr points, int *widths, int count, char *dst,
-                  Bool fallback)
-{
-    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    int i;
-    uint8_t *readpixels_dst = (uint8_t *) dst;
-    void *data;
-    int x_off, y_off;
-    Bool ret = FALSE;
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        goto fail;
-
-    glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off);
-    for (i = 0; i < count; i++) {
-        data = glamor_download_sub_pixmap_to_cpu(pixmap, points[i].x + x_off,
-                                                 points[i].y + y_off, widths[i],
-                                                 1, PixmapBytePad(widths[i],
-                                                                  drawable->
-                                                                  depth),
-                                                 readpixels_dst, 0,
-                                                 GLAMOR_ACCESS_RO);
-        (void)data;
-        assert(data == readpixels_dst);
-        readpixels_dst += PixmapBytePad(widths[i], drawable->depth);
-    }
-
-    ret = TRUE;
-    goto done;
- fail:
-
-    if (!fallback && glamor_ddx_fallback_check_pixmap(drawable))
-        goto done;
-
-    ret = TRUE;
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) {
-        fbGetSpans(drawable, wmax, points, widths, count, dst);
-    }
-    glamor_finish_access(drawable);
- done:
-    return ret;
-}
-
-void
-glamor_get_spans(DrawablePtr drawable,
-                 int wmax,
-                 DDXPointPtr points, int *widths, int count, char *dst)
-{
-    _glamor_get_spans(drawable, wmax, points, widths, count, dst, TRUE);
-}
-
-Bool
-glamor_get_spans_nf(DrawablePtr drawable,
-                    int wmax,
-                    DDXPointPtr points, int *widths, int count, char *dst)
-{
-    return _glamor_get_spans(drawable, wmax, points, widths, count, dst, FALSE);
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 36f9b71..430ca59 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -224,6 +224,9 @@ typedef struct glamor_screen_private {
     /* glamor point shader */
     glamor_program point_prog;
 
+    /* glamor spans shaders */
+    glamor_program_fill fill_spans_program;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -675,19 +678,9 @@ Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
 Bool glamor_solid_boxes(PixmapPtr pixmap,
                         BoxPtr box, int nbox, unsigned long fg_pixel);
 
-/* glamor_fillspans.c */
-void glamor_fill_spans(DrawablePtr drawable,
-                       GCPtr gc,
-                       int n, DDXPointPtr points, int *widths, int sorted);
-
 void glamor_init_solid_shader(ScreenPtr screen);
 void glamor_fini_solid_shader(ScreenPtr screen);
 
-/* glamor_getspans.c */
-void glamor_get_spans(DrawablePtr drawable,
-                      int wmax, DDXPointPtr points, int *widths,
-                      int nspans, char *dst_start);
-
 /* glamor_glyphs.c */
 Bool glamor_realize_glyph_caches(ScreenPtr screen);
 void glamor_glyphs_fini(ScreenPtr screen);
@@ -698,10 +691,6 @@ void glamor_glyphs(CARD8 op,
                    INT16 xSrc,
                    INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs);
 
-/* glamor_setspans.c */
-void glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
-                      DDXPointPtr points, int *widths, int n, int sorted);
-
 /* glamor_polyfillrect.c */
 void glamor_poly_fill_rect(DrawablePtr drawable,
                            GCPtr gc, int nrect, xRectangle *prect);
@@ -968,6 +957,21 @@ RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
                             int dstx, int dsty,
                             unsigned long bitPlane);
 
+/* glamor_spans.c */
+void
+glamor_fill_spans(DrawablePtr drawable,
+                  GCPtr gc,
+                  int n, DDXPointPtr points, int *widths, int sorted);
+
+void
+glamor_get_spans(DrawablePtr drawable, int wmax,
+                 DDXPointPtr points, int *widths, int count, char *dst);
+
+void
+glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
+                 DDXPointPtr points, int *widths, int numPoints, int sorted);
+
+/* glamor_glyphblt.c */
 void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
                             int x, int y, unsigned int nglyph,
                             CharInfoPtr *ppci, void *pglyphBase);
diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c
deleted file mode 100644
index a51e4c5..0000000
--- a/glamor/glamor_setspans.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright © 2009 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>
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- *
- */
-
-#include "glamor_priv.h"
-
-static Bool
-_glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
-                  DDXPointPtr points, int *widths, int numPoints, int sorted,
-                  Bool fallback)
-{
-    PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_pixmap_private *dest_pixmap_priv;
-    int i;
-    uint8_t *drawpixels_src = (uint8_t *) src;
-    RegionPtr clip = fbGetCompositeClip(gc);
-    BoxRec *pbox;
-    int x_off, y_off;
-    Bool ret = FALSE;
-
-    dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
-        glamor_fallback("pixmap has no fbo.\n");
-        goto fail;
-    }
-
-    if (gc->alu != GXcopy) {
-        glamor_fallback("SetSpans with non-copy ALU.\n");
-        goto fail;
-    }
-
-    if (!glamor_set_planemask(dest_pixmap, gc->planemask))
-        goto fail;
-
-    glamor_get_drawable_deltas(drawable, dest_pixmap, &x_off, &y_off);
-    for (i = 0; i < numPoints; i++) {
-
-        int n = REGION_NUM_RECTS(clip);
-
-        pbox = REGION_RECTS(clip);
-        while (n--) {
-            int x1 = points[i].x;
-            int x2 = x1 + widths[i];
-            int y1 = points[i].y;
-
-            if (pbox->y1 > points[i].y || pbox->y2 < points[i].y)
-                break;
-            x1 = x1 > pbox->x1 ? x1 : pbox->x1;
-            x2 = x2 < pbox->x2 ? x2 : pbox->x2;
-            if (x1 >= x2)
-                continue;
-            glamor_upload_sub_pixmap_to_texture(dest_pixmap, x1 + x_off,
-                                                y1 + y_off, x2 - x1, 1,
-                                                PixmapBytePad(widths[i],
-                                                              drawable->depth),
-                                                drawpixels_src, 0);
-        }
-        drawpixels_src += PixmapBytePad(widths[i], drawable->depth);
-    }
-    ret = TRUE;
-    goto done;
-
- fail:
-    if (!fallback && glamor_ddx_fallback_check_pixmap(drawable))
-        goto done;
-
-    glamor_fallback("to %p (%c)\n",
-                    drawable, glamor_get_drawable_location(drawable));
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access_gc(gc)) {
-        fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted);
-    }
-    glamor_finish_access_gc(gc);
-    glamor_finish_access(drawable);
-    ret = TRUE;
-
- done:
-    return ret;
-}
-
-void
-glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
-                 DDXPointPtr points, int *widths, int n, int sorted)
-{
-    _glamor_set_spans(drawable, gc, src, points, widths, n, sorted, TRUE);
-}
-
-Bool
-glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src,
-                    DDXPointPtr points, int *widths, int n, int sorted)
-{
-    return _glamor_set_spans(drawable, gc, src, points,
-                             widths, n, sorted, FALSE);
-}
diff --git a/glamor/glamor_spans.c b/glamor/glamor_spans.c
new file mode 100644
index 0000000..98842cd
--- /dev/null
+++ b/glamor/glamor_spans.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_transform.h"
+#include "glamor_transfer.h"
+
+glamor_program  fill_spans_progs[4];
+
+static const glamor_facet glamor_facet_fillspans_130 = {
+    .name = "fill_spans",
+    .version = 130,
+    .vs_vars =  "attribute vec3 primitive;\n",
+    .vs_exec = ("       vec2 pos = vec2(primitive.z,1) * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
+                GLAMOR_POS(gl_Position, (primitive.xy + pos))),
+};
+
+static const glamor_facet glamor_facet_fillspans_120 = {
+    .name = "fill_spans",
+    .vs_vars =  "attribute vec2 primitive;\n",
+    .vs_exec = ("       vec2 pos = vec2(0,0);\n"
+                GLAMOR_POS(gl_Position, primitive.xy)),
+};
+
+static Bool
+glamor_fill_spans_gl(DrawablePtr drawable,
+                     GCPtr gc,
+                     int n, DDXPointPtr points, int *widths, int sorted)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    glamor_program *prog;
+    int off_x, off_y;
+    GLshort *v;
+    char *vbo_offset;
+    int c;
+    int box_x, box_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    glamor_get_context(glamor_priv);
+
+    if (glamor_priv->glsl_version >= 130) {
+        prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
+                                       &glamor_facet_fillspans_130);
+
+        if (!prog)
+            goto bail_ctx;
+
+        /* Set up the vertex buffers for the points */
+
+        v = glamor_get_vbo_space(drawable->pScreen, n * (4 * sizeof (GLshort)), &vbo_offset);
+
+        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
+        glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
+                              4 * sizeof (GLshort), vbo_offset);
+
+        for (c = 0; c < n; c++) {
+            v[0] = points->x;
+            v[1] = points->y;
+            v[2] = *widths++;
+            points++;
+            v += 4;
+        }
+
+        glamor_put_vbo_space(screen);
+    } else {
+        prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
+                                       &glamor_facet_fillspans_120);
+
+        if (!prog)
+            goto bail_ctx;
+
+        /* Set up the vertex buffers for the points */
+
+        v = glamor_get_vbo_space(drawable->pScreen, n * 8 * sizeof (short), &vbo_offset);
+
+        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
+                              2 * sizeof (short), vbo_offset);
+
+        for (c = 0; c < n; c++) {
+            v[0] = points->x;           v[1] = points->y;
+            v[2] = points->x;           v[3] = points->y + 1;
+            v[4] = points->x + *widths; v[5] = points->y + 1;
+            v[6] = points->x + *widths; v[7] = points->y;
+
+            widths++;
+            points++;
+            v += 8;
+        }
+
+        glamor_put_vbo_space(screen);
+    }
+
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int nbox = RegionNumRects(gc->pCompositeClip);
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, FALSE, prog->matrix_uniform, &off_x, &off_y);
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            if (glamor_priv->glsl_version >= 130)
+                glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n);
+            else {
+                if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+                    glDrawArrays(GL_QUADS, 0, 4 * n);
+                } else {
+                    int i;
+                    for (i = 0; i < n; i++) {
+                        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
+                    }
+                }
+            }
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    if (glamor_priv->glsl_version >= 130)
+        glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    glamor_put_context(glamor_priv);
+    return TRUE;
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    glamor_put_context(glamor_priv);
+bail:
+    return FALSE;
+}
+
+static void
+glamor_fill_spans_bail(DrawablePtr drawable,
+                       GCPtr gc,
+                       int n, DDXPointPtr points, int *widths, int sorted)
+{
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc)) {
+        fbFillSpans(drawable, gc, n, points, widths, sorted);
+    }
+    glamor_finish_access_gc(gc);
+    glamor_finish_access(drawable);
+}
+
+void
+glamor_fill_spans(DrawablePtr drawable,
+                  GCPtr gc,
+                  int n, DDXPointPtr points, int *widths, int sorted)
+{
+    if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted))
+        return;
+    glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted);
+}
+
+Bool
+glamor_fill_spans_nf(DrawablePtr drawable,
+                     GCPtr gc,
+                     int n, DDXPointPtr points, int *widths, int sorted)
+{
+    if (glamor_fill_spans_gl(drawable, gc, n, points, widths, sorted))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+
+    glamor_fill_spans_bail(drawable, gc, n, points, widths, sorted);
+    return TRUE;
+}
+
+static Bool
+glamor_get_spans_gl(DrawablePtr drawable, int wmax,
+                    DDXPointPtr points, int *widths, int count, char *dst)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    int box_x, box_y;
+    int n;
+    char *d;
+    GLenum type;
+    GLenum format;
+    int off_x, off_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+    glamor_format_for_pixmap(pixmap, &format, &type);
+
+    glamor_get_context(glamor_priv);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y);
+
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb);
+        glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
+        d = dst;
+        for (n = 0; n < count; n++) {
+            int x1 = points[n].x + off_x;
+            int y = points[n].y + off_y;
+            int w = widths[n];
+            int x2 = x1 + w;
+            char *l;
+
+            l = d;
+            d += PixmapBytePad(w, drawable->depth);
+
+            /* clip */
+            if (x1 < box->x1) {
+                l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3);
+                x1 = box->x1;
+            }
+            if (x2 > box->x2)
+                x2 = box->x2;
+
+            if (x1 >= x2)
+                continue;
+            if (y < box->y1)
+                continue;
+            if (y >= box->y2)
+                continue;
+
+            glReadPixels(x1 - box->x1, y - box->y1, x2 - x1, 1, format, type, l);
+        }
+    }
+
+    glamor_put_context(glamor_priv);
+    return TRUE;
+bail:
+    return FALSE;
+}
+
+static void
+glamor_get_spans_bail(DrawablePtr drawable, int wmax,
+                 DDXPointPtr points, int *widths, int count, char *dst)
+{
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO))
+        fbGetSpans(drawable, wmax, points, widths, count, dst);
+    glamor_finish_access(drawable);
+}
+
+void
+glamor_get_spans(DrawablePtr drawable, int wmax,
+                 DDXPointPtr points, int *widths, int count, char *dst)
+{
+    if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst))
+        return;
+    glamor_get_spans_bail(drawable, wmax, points, widths, count, dst);
+}
+
+Bool
+glamor_get_spans_nf(DrawablePtr drawable, int wmax,
+                    DDXPointPtr points, int *widths, int count, char *dst)
+{
+    if (glamor_get_spans_gl(drawable, wmax, points, widths, count, dst))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable))
+        return FALSE;
+
+    glamor_get_spans_bail(drawable, wmax, points, widths, count, dst);
+    return TRUE;
+}
+
+static Bool
+glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
+                    DDXPointPtr points, int *widths, int numPoints, int sorted)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    int box_x, box_y;
+    int n;
+    char *s;
+    GLenum type;
+    GLenum format;
+    int off_x, off_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    if (gc->alu != GXcopy)
+        goto bail;
+
+    if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask))
+        goto bail;
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+    glamor_format_for_pixmap(pixmap, &format, &type);
+
+    glamor_get_context(glamor_priv);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y);
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, fbo->tex);
+
+        s = src;
+        for (n = 0; n < numPoints; n++) {
+
+            BoxPtr      clip_box = RegionRects(gc->pCompositeClip);
+            int         nclip_box = RegionNumRects(gc->pCompositeClip);
+            int         w = widths[n];
+            int         y = points[n].y;
+            int         x = points[n].x;
+
+            while (nclip_box--) {
+                int x1 = x;
+                int x2 = x + w;
+                int y1 = y;
+                char *l = s;
+
+                /* clip to composite clip */
+                if (x1 < clip_box->x1) {
+                    l += (clip_box->x1 - x1) * (drawable->bitsPerPixel >> 3);
+                    x1 = clip_box->x1;
+                }
+                if (x2 > clip_box->x2)
+                    x2 = clip_box->x2;
+
+                if (y < clip_box->y1)
+                    continue;
+                if (y >= clip_box->y2)
+                    continue;
+
+                /* adjust to pixmap coordinates */
+                x1 += off_x;
+                x2 += off_x;
+                y1 += off_y;
+
+                if (x1 < box->x1) {
+                    l += (box->x1 - x1) * (drawable->bitsPerPixel >> 3);
+                    x1 = box->x1;
+                }
+                if (x2 > box->x2)
+                    x2 = box->x2;
+
+                if (x1 >= x2)
+                    continue;
+                if (y1 < box->y1)
+                    continue;
+                if (y1 >= box->y2)
+                    continue;
+
+                glTexSubImage2D(GL_TEXTURE_2D, 0,
+                                x1 - box->x1, y1 - box->y1, x2 - x1, 1,
+                                format, type,
+                                l);
+            }
+            s += PixmapBytePad(w, drawable->depth);
+        }
+    }
+
+    glamor_put_context(glamor_priv);
+    return TRUE;
+
+bail:
+    return FALSE;
+}
+
+static void
+glamor_set_spans_bail(DrawablePtr drawable, GCPtr gc, char *src,
+                      DDXPointPtr points, int *widths, int numPoints, int sorted)
+{
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) && glamor_prepare_access_gc(gc))
+        fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted);
+    glamor_finish_access_gc(gc);
+    glamor_finish_access(drawable);
+}
+
+void
+glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
+                 DDXPointPtr points, int *widths, int numPoints, int sorted)
+{
+    if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted))
+        return;
+    glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted);
+}
+
+Bool
+glamor_set_spans_nf(DrawablePtr drawable, GCPtr gc, char *src,
+                    DDXPointPtr points, int *widths, int numPoints, int sorted)
+{
+    if (glamor_set_spans_gl(drawable, gc, src, points, widths, numPoints, sorted))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+
+    glamor_set_spans_bail(drawable, gc, src, points, widths, numPoints, sorted);
+    return TRUE;
+}
commit d78c257f523908760c1b872cc4bef3d42eb31f50
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:43 2014 -0700

    glamor: Add simple upload/download functions in glamor_transfer
    
    These use glTexSubimage2D for upload and glReadPixels for
    download. There are a variety of interfaces to the basic function as
    needed by the callers.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 8555e40..3664fd3 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -24,6 +24,8 @@ libglamor_la_SOURCES = \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_program.c \
+	glamor_transfer.c \
+	glamor_transfer.h \
 	glamor_transform.c \
 	glamor_trapezoid.c \
 	glamor_tile.c \
diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
new file mode 100644
index 0000000..0378bb0
--- /dev/null
+++ b/glamor/glamor_transfer.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_transfer.h"
+
+/* XXX a kludge for now */
+void
+glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type)
+{
+    switch (pixmap->drawable.depth) {
+    case 24:
+    case 32:
+        *format = GL_BGRA;
+        *type = GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case 16:
+        *format = GL_RGB;
+        *type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    case 15:
+        *format = GL_BGRA;
+        *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+    case 8:
+        *format = GL_ALPHA;
+        *type = GL_UNSIGNED_BYTE;
+        break;
+    default:
+        FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth);
+        break;
+    }
+}
+
+/*
+ * Write a region of bits into a pixmap
+ */
+void
+glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                    int dx_src, int dy_src,
+                    int dx_dst, int dy_dst,
+                    uint8_t *bits, uint32_t byte_stride)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
+    int                         box_x, box_y;
+    int                         bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
+    GLenum                      type;
+    GLenum                      format;
+
+    glamor_format_for_pixmap(pixmap, &format, &type);
+
+    glamor_get_context(glamor_priv);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+
+    glamor_pixmap_loop(priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
+        BoxPtr                  boxes = in_boxes;
+        int                     nbox = in_nbox;
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, fbo->tex);
+
+        while (nbox--) {
+
+            /* compute drawable coordinates */
+            int x1 = boxes->x1 + dx_dst;
+            int x2 = boxes->x2 + dx_dst;
+            int y1 = boxes->y1 + dy_dst;
+            int y2 = boxes->y2 + dy_dst;
+
+            boxes++;
+
+            if (x1 < box->x1)
+                x1 = box->x1;
+            if (box->x2 < x2)
+                x2 = box->x2;
+
+            if (x2 <= x1)
+                continue;
+
+            if (y1 < box->y1)
+                y1 = box->y1;
+            if (box->y2 < y2)
+                y2 = box->y2;
+
+            if (y2 <= y1)
+                continue;
+
+            glPixelStorei(GL_UNPACK_SKIP_ROWS, y1 - dy_dst + dy_src);
+            glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1 - dx_dst + dx_src);
+
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                            x1 - box->x1, y1 - box->y1,
+                            x2 - x1, y2 - y1,
+                            format, type,
+                            bits);
+        }
+    }
+
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+    glamor_put_context(glamor_priv);
+}
+
+/*
+ * Upload a region of data
+ */
+
+void
+glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
+                     int region_x, int region_y,
+                     uint8_t *bits, uint32_t byte_stride)
+{
+    glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
+                        -region_x, -region_y,
+                        0, 0,
+                        bits, byte_stride);
+}
+
+/*
+ * Take the data in the pixmap and stuff it back into the FBO
+ */
+void
+glamor_upload_pixmap(PixmapPtr pixmap)
+{
+    BoxRec box;
+
+    box.x1 = 0;
+    box.x2 = pixmap->drawable.width;
+    box.y1 = 0;
+    box.y2 = pixmap->drawable.height;
+    glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
+                        pixmap->devPrivate.ptr, pixmap->devKind);
+}
+
+/*
+ * Read stuff from the pixmap FBOs and write to memory
+ */
+void
+glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                      int dx_src, int dy_src,
+                      int dx_dst, int dy_dst,
+                      uint8_t *bits, uint32_t byte_stride)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
+    int box_x, box_y;
+    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
+    GLenum type;
+    GLenum format;
+
+    glamor_format_for_pixmap(pixmap, &format, &type);
+
+    glamor_get_context(glamor_priv);
+
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
+    glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+
+    glamor_pixmap_loop(priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
+        BoxPtr                  boxes = in_boxes;
+        int                     nbox = in_nbox;
+
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb);
+
+        while (nbox--) {
+
+            /* compute drawable coordinates */
+            int                     x1 = boxes->x1 + dx_src;
+            int                     x2 = boxes->x2 + dx_src;
+            int                     y1 = boxes->y1 + dy_src;
+            int                     y2 = boxes->y2 + dy_src;
+
+            boxes++;
+
+            if (x1 < box->x1)
+                x1 = box->x1;
+            if (box->x2 < x2)
+                x2 = box->x2;
+
+            if (y1 < box->y1)
+                y1 = box->y1;
+            if (box->y2 < y2)
+                y2 = box->y2;
+
+            if (x2 <= x1)
+                continue;
+            if (y2 <= y1)
+                continue;
+
+            glPixelStorei(GL_PACK_SKIP_PIXELS, x1 - dx_src + dx_dst);
+            glPixelStorei(GL_PACK_SKIP_ROWS, y1 - dy_src + dy_dst);
+            glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits);
+        }
+    }
+    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+    glamor_put_context(glamor_priv);
+}
+
+/*
+ * Read data from the pixmap FBO
+ */
+void
+glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits)
+{
+    BoxRec      box;
+
+    box.x1 = x;
+    box.x2 = x + w;
+    box.y1 = y;
+    box.y2 = y + h;
+
+    glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y,
+                          bits, PixmapBytePad(w, pixmap->drawable.depth));
+}
+
+/*
+ * Pull the data from the FBO down to the pixmap
+ */
+void
+glamor_download_pixmap(PixmapPtr pixmap)
+{
+    BoxRec      box;
+
+    box.x1 = 0;
+    box.x2 = pixmap->drawable.width;
+    box.y1 = 0;
+    box.y2 = pixmap->drawable.height;
+
+    glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0,
+                          pixmap->devPrivate.ptr, pixmap->devKind);
+}
diff --git a/glamor/glamor_transfer.h b/glamor/glamor_transfer.h
new file mode 100644
index 0000000..de8186a
--- /dev/null
+++ b/glamor/glamor_transfer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _GLAMOR_TRANSFER_H_
+#define _GLAMOR_TRANSFER_H_
+
+void
+glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type);
+
+void
+glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                    int dx_src, int dy_src,
+                    int dx_dst, int dy_dst,
+                    uint8_t *bits, uint32_t byte_stride);
+
+void
+glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
+                     int region_x, int region_y,
+                     uint8_t *bits, uint32_t byte_stride);
+
+void
+glamor_upload_pixmap(PixmapPtr pixmap);
+
+void
+glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                      int dx_src, int dy_src,
+                      int dx_dst, int dy_dst,
+                      uint8_t *bits, uint32_t byte_stride);
+
+void
+glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits);
+
+void
+glamor_download_pixmap(PixmapPtr pixmap);
+
+#endif /* _GLAMOR_TRANSFER_H_ */
commit 693e6bea897e4c9473a9f22dd8b90df3437e04a1
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:42 2014 -0700

    glamor: Use plain GLSL 1.20 features for fill code.
    
    This prevents performance regressions from losing acceleration support
    on older hardware as we transition to using glamor_program.c for
    acceleration.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index 5996ed9..0f4d0f0 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -45,9 +45,8 @@ use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
 
 static const glamor_facet glamor_fill_tile = {
     .name = "tile",
-    .version = 130,
-    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + pos;\n",
-    .fs_exec =  "       gl_FragColor = texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0);\n",
+    .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
+    .fs_exec =  "       gl_FragColor = texture2D(sampler, fill_pos);\n",
     .locations = glamor_program_location_fill,
     .use = use_tile,
 };
@@ -108,6 +107,7 @@ static glamor_location_var location_vars[] = {
     {
         .location = glamor_program_location_fill,
         .vs_vars = ("uniform vec2 fill_offset;\n"
+                    "uniform vec2 fill_size;\n"
                     "varying vec2 fill_pos;\n"),
         .fs_vars = ("uniform sampler2D sampler;\n"
                     "uniform vec2 fill_size;\n"
commit 5b76b3978d792c92b23a691204b473209782476e
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:42 2014 -0700

    glamor: Compute supported GLSL version and save in screen private
    
    This currently computes the GLSL version in a fairly naïve fashion,
    and leaves that in the screen private for other users. This will let
    us update the version computation in one place later on.
    
    v2: Drop an accidental rebase-squashed hunk (change by anholt).
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index a7d981c..d7192c1 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -353,6 +353,15 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 
     gl_version = epoxy_gl_version();
 
+    /* Would be nice to have a cleaner test for GLSL 1.30 support,
+     * but for now this should suffice
+     */
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && gl_version >= 30)
+        glamor_priv->glsl_version = 130;
+    else
+        glamor_priv->glsl_version = 120;
+
+
     /* We'd like to require GL_ARB_map_buffer_range or
      * GL_OES_map_buffer_range, since it offers more information to
      * the driver than plain old glMapBuffer() or glBufferSubData().
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 4c305ab..36f9b71 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -205,6 +205,7 @@ typedef struct glamor_screen_private {
     Bool yInverted;
     unsigned int tick;
     enum glamor_gl_flavor gl_flavor;
+    int glsl_version;
     int has_pack_invert;
     int has_fbo_blit;
     int has_map_buffer_range;
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index e2e1434..5996ed9 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -240,16 +240,8 @@ glamor_build_program(ScreenPtr          screen,
     flags |= fill->flags;
     version = MAX(version, fill->version);
 
-    if (version >= 130) {
-
-        /* Would be nice to have a cleaner test for GLSL 1.30 support,
-         * but for now this should suffice
-         */
-        if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP ||
-            epoxy_gl_version() < 30) {
-            goto fail;
-        }
-    }
+    if (version > glamor_priv->glsl_version)
+        goto fail;
 
     vs_vars = vs_location_vars(locations);
     fs_vars = fs_location_vars(locations);
commit 3c2c59eed3c68c0e5a93c38cf01eedad015e3157
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 21:15:41 2014 -0700

    fb: Publish fbGlyphs and fbUnrealizeGlyph
    
    This lets other code jump directly into the fb code for fallbacks
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/fb/fbpict.c b/fb/fbpict.c
index b503858..c2ee8a5 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -82,7 +82,7 @@ fbDestroyGlyphCache(void)
     }
 }
 
-static void
+void
 fbUnrealizeGlyph(ScreenPtr pScreen,
 		 GlyphPtr pGlyph)
 {
@@ -90,7 +90,7 @@ fbUnrealizeGlyph(ScreenPtr pScreen,
 	pixman_glyph_cache_remove (glyphCache, pGlyph, NULL);
 }
 
-static void
+void
 fbGlyphs(CARD8 op,
 	 PicturePtr pSrc,
 	 PicturePtr pDst,
diff --git a/fb/fbpict.h b/fb/fbpict.h
index 110f32d..8b0f59f 100644
--- a/fb/fbpict.h
+++ b/fb/fbpict.h
@@ -65,11 +65,24 @@ fbTrapezoids(CARD8 op,
              INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps);
 
 extern _X_EXPORT void
-
 fbTriangles(CARD8 op,
             PicturePtr pSrc,
             PicturePtr pDst,
             PictFormatPtr maskFormat,
             INT16 xSrc, INT16 ySrc, int ntris, xTriangle * tris);
 
+extern _X_EXPORT void
+fbUnrealizeGlyph(ScreenPtr pScreen,
+		 GlyphPtr pGlyph);
+
+extern _X_EXPORT void
+fbGlyphs(CARD8 op,
+	 PicturePtr pSrc,
+	 PicturePtr pDst,
+	 PictFormatPtr maskFormat,
+	 INT16 xSrc,
+	 INT16 ySrc, int nlist,
+	 GlyphListPtr list,
+	 GlyphPtr *glyphs);
+
 #endif                          /* _FBPICT_H_ */
commit 9dffcda804b2609f0b319d35dd47fd401d4fafce
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 20:54:22 2014 -0700

    glamor: Bail from composite when pixmap cannot be uploaded
    
    I think the sense of the return value was just flipped here; if you
    return TRUE, then the calling code assumes that the pixmap *has* been
    uploaded and that an FBO is available. When it tries to use it, it
    crashes though. Returning false makes the caller bail back to software.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index c275af7..a811f60 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -978,7 +978,7 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
                                                &no_alpha,
                                                &revert, &swap_rb, 1)) {
         glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
-        return TRUE;
+        return FALSE;
     }
     if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
         return FALSE;
commit 15fec3bc3a2d29c903f35b5a30ac09e196eb36b1
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 20:54:21 2014 -0700

    glamor: Remove warning message when pixmap cannot be stored in a texture
    
    This happens when you have 4bpp pixmaps; it's not an error, so stop
    flooding the log file when it happens.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 891ecdd..c275af7 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -283,8 +283,6 @@ glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
         break;
 
     default:
-        LogMessageVerb(X_INFO, 0,
-                       "fail to get matched format for %x \n", format);
         return -1;
     }
     return 0;
commit 5f177f3582323b6c1791e9e2c107548b607369de
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 20:54:20 2014 -0700

    glamor: Public polyLines function is glamor_poly_lines_nf
    
    There was a spurious declaratoin in glamor.h for glamor_poly_line_nf
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 11ec493..2ff0409 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -431,9 +431,6 @@ extern _X_EXPORT Bool glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC,
 extern _X_EXPORT Bool glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC,
                                              int nseg, xSegment *pSeg);
 
-extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC,
-                                          int mode, int npt, DDXPointPtr ppt);
-
 extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
                                            int mode, int n, DDXPointPtr points);
 
commit 6aac97198f60de9d4e415fb4fa2fc11cac6c6790
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 20:54:19 2014 -0700

    glamor: Initialize XV shaders from glamor_xv_init instead of glamor_init
    
    The glamor_init calls to glamor_init_xv_shader were never getting run
    because GLAMOR_XV was never defined. Instead of trying to make that
    work, fix glamor_xv_init to make the call instead.
    
    Further, just get rid of the glamor_fini_xv_shader function entirely
    as the shader program will be destroyed when the context is destroyed
    at server reset time.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 971dbf8..a7d981c 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -494,9 +494,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 #ifdef GLAMOR_GRADIENT_SHADER
     glamor_init_gradient_shader(screen);
 #endif
-#ifdef GLAMOR_XV
-    glamor_init_xv_shader(screen);
-#endif
     glamor_pixmap_init(screen);
     glamor_glyphs_init(screen);
 
@@ -516,9 +513,6 @@ glamor_release_screen_priv(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-#ifdef GLAMOR_XV
-    glamor_fini_xv_shader(screen);
-#endif
 #ifdef RENDER
     glamor_fini_composite_shaders(screen);
 #endif
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 17745a4..4e60fa3 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -114,18 +114,6 @@ glamor_init_xv_shader(ScreenPtr screen)
     glamor_put_context(glamor_priv);
 }
 
-void
-glamor_fini_xv_shader(ScreenPtr screen)
-{
-    glamor_screen_private *glamor_priv;
-
-    glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
-
-    glDeleteProgram(glamor_priv->xv_prog);
-    glamor_put_context(glamor_priv);
-}
-
 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
@@ -559,6 +547,8 @@ glamor_xv_init(ScreenPtr screen, int num_texture_ports)
     XF86VideoAdaptorPtr adapt;
     int i;
 
+    glamor_init_xv_shader(screen);
+
     adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
                    (sizeof(glamor_port_private) + sizeof(DevUnion)));
     if (adapt == NULL)
commit 1707faf36d49a63efc462dfef133a555fe093832
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 20:54:18 2014 -0700

    glamor: SetWindowPixmap is not related to RENDER
    
    Move the configuration of screen->SetWindowPixmap out from under it.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 3094432..971dbf8 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -475,13 +475,13 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_priv->saved_procs.create_picture = ps->CreatePicture;
     ps->CreatePicture = glamor_create_picture;
 
-    glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap;
-    screen->SetWindowPixmap = glamor_set_window_pixmap;
-
     glamor_priv->saved_procs.destroy_picture = ps->DestroyPicture;
     ps->DestroyPicture = glamor_destroy_picture;
     glamor_init_composite_shaders(screen);
 #endif
+    glamor_priv->saved_procs.set_window_pixmap = screen->SetWindowPixmap;
+    screen->SetWindowPixmap = glamor_set_window_pixmap;
+
     glamor_init_vbo(screen);
     glamor_init_pixmap_fbo(screen);
     glamor_init_solid_shader(screen);
commit 8d88b90953471ead3b480b6ae9d7280b8bd6b216
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 1 20:54:15 2014 -0700

    glamor: glamor_poly_point_nf cannot fail for non-DDX pixmaps
    
    All of the glamor _nf functions must check to see if the DDX can
    access the pixmap directly before returning failure back to the
    driver; this restructures the point code to split out the _nf checking
    from the _gl code.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_points.c b/glamor/glamor_points.c
index 5399f96..0d58e55 100644
--- a/glamor/glamor_points.c
+++ b/glamor/glamor_points.c
@@ -35,8 +35,8 @@ static const glamor_facet glamor_facet_point = {
     .vs_exec = GLAMOR_POS(gl_Position, primitive),
 };
 
-Bool
-glamor_poly_point_nf(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPointPtr ppt)
+static Bool
+glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPointPtr ppt)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -123,7 +123,22 @@ void
 glamor_poly_point(DrawablePtr drawable, GCPtr gc, int mode, int npt,
                   DDXPointPtr ppt)
 {
-    if (glamor_poly_point_nf(drawable, gc, mode, npt, ppt))
+    if (glamor_poly_point_gl(drawable, gc, mode, npt, ppt))
         return;
     miPolyPoint(drawable, gc, mode, npt, ppt);
 }
+
+Bool
+glamor_poly_point_nf(DrawablePtr drawable, GCPtr gc, int mode, int npt,
+                     DDXPointPtr ppt)
+{
+    if (glamor_poly_point_gl(drawable, gc, mode, npt, ppt))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+
+    miPolyPoint(drawable, gc, mode, npt, ppt);
+    return TRUE;
+}
+
commit d5dd1d6371021c2aad94e33c5837ccd4bf9bf0f4
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 21 13:13:27 2014 -0700

    Revert "glx: Make sure we get an FBConfig the root window's visual."
    
    This reverts commit b5a61239e2fef167c229154d7919ff862503e3f3.
    
    Not only did I screw up and introduce a warning, it turns out
    glXChooseFBConfig() explicitly ignores this attribute.  Thanks, GLX.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Julien Cristau <jcristau at debian.org>

diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index 9903cc7..eaf5654 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -313,7 +313,6 @@ ephyr_glamor_get_visual(void)
         GLX_GREEN_SIZE, 1,
         GLX_BLUE_SIZE, 1,
         GLX_DOUBLEBUFFER, 1,
-        GLX_VISUAL_ID, DefaultVisual(dpy, DefaultScreen(dpy)),
         None
     };
     int event_base = 0, error_base = 0, nelements;
commit 84f977467b514af88019ab2791bf7a74530b54df
Merge: 9d20d18 9892471
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Apr 3 10:44:28 2014 -0700

    Merge remote-tracking branch 'whot/for-keith'

commit 98924719d524bf87cdf301063cd744d1271c33ff
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Apr 2 13:55:10 2014 +1000

    Revert "xkb: ProcesssPointerEvent must work on the VCP if it gets the VCP"
    
    This was the wrong fix to the problem, and it triggered a change in XKB
    behavior: previously a button event would unlock a latched modifier, now it
    doesn't anymore.
    https://bugs.freedesktop.org/show_bug.cgi?id=73155
    
    Note that the new behavior is is strictly spec compliant but we've had the
    other behavior for a long time so we shouldn't break it.
    
    The bug this patch originally fixed was a null-pointer dereference when
    releasing button events on server shutdown. This was addressed by the commit
    below, so the need for this patch has gone away anyway.
    
    commit 3e4be4033aed78b2bb3a18d51f0963989efd1af3
    Author: Peter Hutterer <peter.hutterer at who-t.net>
    Date:   Fri Jan 25 11:47:32 2013 +1000
    
        dix: when shutting down slave devices, shut down xtest devices last
    
    This reverts commit 2decff6393a44b56d80d53570718f95354fde454.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index cb4bca0..5f3de0d 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -711,7 +711,7 @@ ProcessPointerEvent(InternalEvent *ev, DeviceIntPtr mouse)
     xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse);
     DeviceEvent *event = &ev->device_event;
 
-    dev = (IsMaster(mouse) || IsFloating(mouse)) ? mouse : GetMaster(mouse, MASTER_KEYBOARD);
+    dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD);
 
     if (dev && dev->key) {
         xkbi = dev->key->xkbInfo;
commit 9d65c515d83d2158b5949e249777ca2a02b31901
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Apr 1 11:24:17 2014 +0200

    xf86LogInit: log to XDG_DATA_HOME when not running as root
    
    When no logfile was specified (xf86LogFileFrom == X_DEFAULT) and we're not
    running as root log to $XDG_DATA_HOME/xorg/Xorg.#.log as Xorg won't be able to
    log to the default /var/log/... when it is not running as root.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index bc643e8..cdd3258 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2043,6 +2043,8 @@ if test "x$XORG" = xyes; then
 	AC_SUBST(XF86CONFIGDIR)
 	CONFIGFILE="$sysconfdir/$XF86CONFIGFILE"
 	LOGPREFIX="Xorg."
+	XDG_DATA_HOME=".local/share"
+	XDG_DATA_HOME_LOGDIR="xorg"
 	AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
 	AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
 	AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
@@ -2057,6 +2059,8 @@ if test "x$XORG" = xyes; then
 	AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path])
 	AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location])
 	AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default logfile prefix])
+	AC_DEFINE_DIR(DEFAULT_XDG_DATA_HOME, XDG_DATA_HOME, [Default XDG_DATA dir under HOME])
+	AC_DEFINE_DIR(DEFAULT_XDG_DATA_HOME_LOGDIR, XDG_DATA_HOME_LOGDIR, [Default log dir under XDG_DATA_HOME])
 	AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
 	if test "x$VGAHW" = xyes; then
 		AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module])
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 12a8771..e2b32a0 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1217,16 +1217,45 @@ xf86ErrorF(const char *format, ...)
     va_end(ap);
 }
 
+/* Note temporarily modifies the passed in buffer! */
+static void xf86_mkdir_p(char *path)
+{
+    char *sep = path;
+
+    while ((sep = strchr(sep + 1, '/'))) {
+        *sep = 0;
+        (void)mkdir(path, 0777);
+        *sep = '/';
+    }
+    (void)mkdir(path, 0777);
+}
+
 void
 xf86LogInit(void)
 {
-    char *lf = NULL;
+    char *env, *lf = NULL;
+    char buf[PATH_MAX];
 
 #define LOGSUFFIX ".log"
 #define LOGOLDSUFFIX ".old"
 
     /* Get the log file name */
     if (xf86LogFileFrom == X_DEFAULT) {
+        /* When not running as root, we won't be able to write to /var/log */
+        if (geteuid() != 0) {
+            if ((env = getenv("XDG_DATA_HOME")))
+                snprintf(buf, sizeof(buf), "%s/%s", env,
+                         DEFAULT_XDG_DATA_HOME_LOGDIR);
+            else if ((env = getenv("HOME")))
+                snprintf(buf, sizeof(buf), "%s/%s/%s", env,
+                         DEFAULT_XDG_DATA_HOME, DEFAULT_XDG_DATA_HOME_LOGDIR);
+
+            if (env) {
+                xf86_mkdir_p(buf);
+                strlcat(buf, "/" DEFAULT_LOGPREFIX, sizeof(buf));
+                xf86LogFile = buf;
+            }
+        }
         /* Append the display number and ".log" */
         if (asprintf(&lf, "%s%%s" LOGSUFFIX, xf86LogFile) == -1)
             FatalError("Cannot allocate space for the log file name\n");
diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man
index 0cd5a10..3ff6aef 100644
--- a/hw/xfree86/man/Xorg.man
+++ b/hw/xfree86/man/Xorg.man
@@ -301,9 +301,11 @@ Use the file called
 .I filename
 as the
 .B Xorg
-server log file.  The default log file is
+server log file.  The default log file when running as root is
 .BI __logdir__/Xorg. n .log
-on most platforms, where
+and for non root it is
+.BI $XDG_DATA_HOME/xorg/Xorg. n .log
+where
 .I n
 is the display number of the
 .B Xorg
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index 85f9f2e..6d2652e 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -442,11 +442,15 @@ __modulepath__
 .TP 7
 .BI "LogFile \*q" path \*q
 sets the name of the Xorg server log file.
-The default log file name is
+The default log file name when running as root is
 .PP
 .RS 11
 .RI __logdir__/Xorg. <n> .log
 .RE
+and for non root it is
+.RS 11
+.RI $XDG_DATA_HOME/xorg/Xorg. <n> .log
+.RE
 .PP
 .RS 7
 where
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 4e2a45b..629ae40 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -51,6 +51,12 @@
 /* Default logfile prefix */
 #undef DEFAULT_LOGPREFIX
 
+/* Default XDG_DATA dir under HOME */
+#undef DEFAULT_XDG_DATA_HOME
+
+/* Default log dir under XDG_DATA_HOME */
+#undef DEFAULT_XDG_DATA_HOME_LOGDIR
+
 /* Building DRI-capable DDX. */
 #undef XF86DRI
 
commit e738276e96590b2230dd9d9f5a3f9485f592e1e6
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Mar 31 18:04:07 2014 -0700

    glamor: Expose glamor_destroy_pixmap()
    
    When we create a glamor pixmap by calling glamor_create_pixmap()
    directly, we need to call glamor_destroy_pixmap() to destroy it.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 913bdce..27c9cb3 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -143,6 +143,7 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
 
 extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
                                                 int depth, unsigned int usage);
+extern _X_EXPORT Bool glamor_destroy_pixmap(PixmapPtr pixmap);
 
 #define GLAMOR_CREATE_PIXMAP_CPU        0x100
 #define GLAMOR_CREATE_PIXMAP_FIXUP      0x101
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 6aa2f74..e8925a6 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -584,8 +584,6 @@ extern int glamor_debug_level;
 /* glamor.c */
 PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable);
 
-Bool glamor_destroy_pixmap(PixmapPtr pixmap);
-
 glamor_pixmap_fbo *glamor_pixmap_detach_fbo(glamor_pixmap_private *
                                             pixmap_priv);
 void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo);
commit d14803437582668f5ffea14071ea962b6b8e450d
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Mar 31 18:00:54 2014 -0700

    glamor: Add new GLAMOR_CREATE_PIXMAP_NO_TEXTURE pixmap create flag
    
    This flag lets a DDX allocate a glamor pixmap without allocating the
    texture that backs it.  The DDX can then allocate the texture itself
    and then set it later.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 3094432..8d24531 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -182,7 +182,15 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
     pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
     screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
 
-    if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
+    if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) {
+        pixmap_priv->type = GLAMOR_TEXTURE_ONLY;
+        pixmap_priv->base.box.x1 = 0;
+        pixmap_priv->base.box.y1 = 0;
+        pixmap_priv->base.box.x2 = w;
+        pixmap_priv->base.box.y2 = h;
+        return pixmap;
+    }
+    else if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
         glamor_check_fbo_size(glamor_priv, w, h))
     {
         pixmap_priv->type = type;
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 84b6736..913bdce 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -149,6 +149,7 @@ extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
 #define GLAMOR_CREATE_FBO_NO_FBO        0x103
 #define GLAMOR_CREATE_PIXMAP_MAP        0x104
 #define GLAMOR_CREATE_NO_LARGE          0x105
+#define GLAMOR_CREATE_PIXMAP_NO_TEXTURE 0x106
 
 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo).
  *
commit fe204185bc801bb17785dc8d1cde09d48b5e257f
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Mar 31 17:59:18 2014 -0700

    glamor: Move glamor_egl_screen_init() prototype to glamor.h
    
    A DDX that implements the glamor EGL functions need to pull in this
    prototype but shouldn't need to pull in glamor_priv.h
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 11ec493..84b6736 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -310,6 +310,8 @@ extern _X_EXPORT Bool
 
 #endif
 
+extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
+                                             struct glamor_context *glamor_ctx);
 extern _X_EXPORT void glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap);
 
 extern _X_EXPORT int glamor_create_gc(GCPtr gc);
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index 4fd9e80..028d1cc 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -26,7 +26,9 @@
  * Stubbed out glamor_egl.c functions for servers other than Xorg.
  */
 
-#include "glamor_priv.h"
+#include "dix-config.h"
+
+#include "glamor.h"
 
 void
 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 4c305ab..6aa2f74 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -992,9 +992,6 @@ void glamor_composite_rectangles(CARD8 op,
                                  xRenderColor *color,
                                  int num_rects, xRectangle *rects);
 
-extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
-                                             struct glamor_context *glamor_ctx);
-
 /* glamor_xv */
 typedef struct {
     uint32_t transform_index;
commit 9ba2084321b1ac8d271feefee4f5b968d34226d6
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Mar 27 23:47:59 2014 -0700

    dri3: Allow asynchronous implementation for dri3_open
    
    By passing the client pointer to the dri3_open implementation, we allow
    the clients to implement the open callback asynchronously.  If the
    client ignore count is positive after returning from dri3_open, we
    assume that authentication is in progress and doesn't send the reply.
    The code to send the reply is moved into a helper function, which the
    implementation can call upon receiving its authenticaion reply.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dri3/dri3.h b/dri3/dri3.h
index 7c0c330..1c04cbd 100644
--- a/dri3/dri3.h
+++ b/dri3/dri3.h
@@ -32,7 +32,8 @@
 
 #define DRI3_SCREEN_INFO_VERSION        0
 
-typedef int (*dri3_open_proc)(ScreenPtr screen,
+typedef int (*dri3_open_proc)(ClientPtr client,
+                              ScreenPtr screen,
                               RRProviderPtr provider,
                               int *fd);
 
@@ -60,6 +61,9 @@ typedef struct dri3_screen_info {
 extern _X_EXPORT Bool
 dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
 
+extern _X_EXPORT int
+dri3_send_open_reply(ClientPtr client, int fd);
+
 #endif
 
 #endif /* _DRI3_H_ */
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
index 31dce83..fe45620 100644
--- a/dri3/dri3_request.c
+++ b/dri3/dri3_request.c
@@ -55,16 +55,35 @@ proc_dri3_query_version(ClientPtr client)
     return Success;
 }
 
-static int
-proc_dri3_open(ClientPtr client)
+int
+dri3_send_open_reply(ClientPtr client, int fd)
 {
-    REQUEST(xDRI3OpenReq);
     xDRI3OpenReply rep = {
         .type = X_Reply,
         .nfd = 1,
         .sequenceNumber = client->sequence,
         .length = 0,
     };
+
+    if (client->swapped) {
+        swaps(&rep.sequenceNumber);
+        swapl(&rep.length);
+    }
+
+    if (WriteFdToClient(client, fd, TRUE) < 0) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    WriteToClient(client, sizeof (rep), &rep);
+
+    return Success;
+}
+
+static int
+proc_dri3_open(ClientPtr client)
+{
+    REQUEST(xDRI3OpenReq);
     RRProviderPtr provider;
     DrawablePtr drawable;
     ScreenPtr screen;
@@ -92,17 +111,8 @@ proc_dri3_open(ClientPtr client)
     if (status != Success)
         return status;
 
-    if (client->swapped) {
-        swaps(&rep.sequenceNumber);
-        swapl(&rep.length);
-    }
-
-    if (WriteFdToClient(client, fd, TRUE) < 0) {
-        close(fd);
-        return BadAlloc;
-    }
-
-    WriteToClient(client, sizeof (rep), &rep);
+    if (client->ignoreCount == 0)
+        return dri3_send_open_reply(client, fd);
 
     return Success;
 }
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
index c880296..bbf1d05 100644
--- a/dri3/dri3_screen.c
+++ b/dri3/dri3_screen.c
@@ -40,7 +40,7 @@ dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
     if (!info || !info->open)
         return BadMatch;
 
-    rc = (*info->open) (screen, provider, fd);
+    rc = (*info->open) (client, screen, provider, fd);
     if (rc != Success)
         return rc;
 
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 8123421..e2b6a92 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -608,7 +608,8 @@ glamor_egl_close_screen(ScreenPtr screen)
 }
 
 static int
-glamor_dri3_open(ScreenPtr screen,
+glamor_dri3_open(ClientPtr client,
+                 ScreenPtr screen,
                  RRProviderPtr provider,
                  int *fdp)
 {
commit 4ba7b594464887ae68623e150348d90812eec36c
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Mar 27 22:15:28 2014 -0700

    composite: Add exception mechanism for implicit redirection policy
    
    Normally composite will decide to add implicit redirection when a
    window with an alternate visual is a parent of a window with a regular
    visual or vice versa.  This uses extra pixmap memory and incurs an extra
    copy.  This exception mechanism provides a way for a DDX to override this
    if the DDX knows that its acceleration architecture will render correctly.
    
    The relevant case is that of an RGB window reparented into a ARGB parent
    frame window.  If the DDX knows that the acceleration architecture in use
    will pad the alpha channel to opaque when rendering to the RGB window,
    the implicit redirection can be avoided.
    
    This patch adds a new composite function:
    
      CompositeRegisterImplicitRedirectionException()
    
    which lets a DDX register a pair of parent and child window visuals, that
    will not be implicitly redirected even if the normal policy would have
    made that choice.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/composite/compinit.c b/composite/compinit.c
index 1db9e0b..48e938f 100644
--- a/composite/compinit.c
+++ b/composite/compinit.c
@@ -229,6 +229,28 @@ CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids,
     return compRegisterAlternateVisuals(cs, vids, nVisuals);
 }
 
+Bool
+CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen,
+                                              VisualID parentVisual,
+                                              VisualID winVisual)
+{
+    CompScreenPtr cs = GetCompScreen(pScreen);
+    CompImplicitRedirectException *p;
+
+    p = realloc(cs->implicitRedirectExceptions,
+                sizeof(p[0]) * (cs->numImplicitRedirectExceptions + 1));
+    if (p == NULL)
+        return FALSE;
+
+    p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual;
+    p[cs->numImplicitRedirectExceptions].winVisual = winVisual;
+
+    cs->implicitRedirectExceptions = p;
+    cs->numImplicitRedirectExceptions++;
+
+    return TRUE;
+}
+
 typedef struct _alternateVisual {
     int depth;
     CARD32 format;
@@ -349,6 +371,8 @@ compScreenInit(ScreenPtr pScreen)
 
     cs->numAlternateVisuals = 0;
     cs->alternateVisuals = NULL;
+    cs->numImplicitRedirectExceptions = 0;
+    cs->implicitRedirectExceptions = NULL;
 
     if (!compAddAlternateVisuals(pScreen, cs)) {
         free(cs);
diff --git a/composite/compint.h b/composite/compint.h
index 12dc8b3..56b76c5 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -119,6 +119,11 @@ typedef struct _CompOverlayClientRec {
     XID resource;
 } CompOverlayClientRec;
 
+typedef struct _CompImplicitRedirectException {
+    XID parentVisual;
+    XID winVisual;
+} CompImplicitRedirectException;
+
 typedef struct _CompScreen {
     PositionWindowProcPtr PositionWindow;
     CopyWindowProcPtr CopyWindow;
@@ -155,6 +160,8 @@ typedef struct _CompScreen {
     CloseScreenProcPtr CloseScreen;
     int numAlternateVisuals;
     VisualID *alternateVisuals;
+    int numImplicitRedirectExceptions;
+    CompImplicitRedirectException *implicitRedirectExceptions;
 
     WindowPtr pOverlayWin;
     Window overlayWid;
diff --git a/composite/compositeext.h b/composite/compositeext.h
index 0b148f0..b96cb1d 100644
--- a/composite/compositeext.h
+++ b/composite/compositeext.h
@@ -35,6 +35,10 @@ extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen,
                                                         VisualID * vids,
                                                         int nVisuals);
 
+extern _X_EXPORT Bool CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen,
+                                                                    VisualID parentVisual,
+                                                                    VisualID winVisual);
+
 extern _X_EXPORT RESTYPE CompositeClientWindowType;
 
 #endif                          /* _COMPOSITEEXT_H_ */
diff --git a/composite/compwindow.c b/composite/compwindow.c
index 6c24349..8824294 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -336,6 +336,21 @@ compIsAlternateVisual(ScreenPtr pScreen, XID visual)
 }
 
 static Bool
+compIsImplicitRedirectException(ScreenPtr pScreen,
+                                XID parentVisual, XID winVisual)
+{
+    CompScreenPtr cs = GetCompScreen(pScreen);
+    int i;
+
+    for (i = 0; i < cs->numImplicitRedirectExceptions; i++)
+        if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual &&
+            cs->implicitRedirectExceptions[i].winVisual == winVisual)
+            return TRUE;
+
+    return FALSE;
+}
+
+static Bool
 compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
 {
     if (pParent) {
@@ -343,6 +358,9 @@ compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
         XID winVisual = wVisual(pWin);
         XID parentVisual = wVisual(pParent);
 
+        if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual))
+            return FALSE;
+
         if (winVisual != parentVisual &&
             (compIsAlternateVisual(pScreen, winVisual) ||
              compIsAlternateVisual(pScreen, parentVisual)))
commit 73698d41e41ce76bef2d9a90b46ac0c24ae148dd
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 31 23:55:25 2014 -0700

    Make XYToWindow a screen function
    
    This allows DDXen to override the window picking to account for
    native windows not seen by the X server.  The bulk of the picking logic
    is exposed as a new helper function, miSpriteTrace().  This function
    completes the sprite trace filled out by the caller, and can be set up
    to start the search from a given toplevel window.
    
    v2: Leave existing XYToWindow API in place for API compatibility
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/dix/events.c b/dix/events.c
index f05dada..125a0ee 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2835,7 +2835,7 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
     return deliveries;
 }
 
-static Bool
+Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
@@ -2876,49 +2876,9 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
 WindowPtr
 XYToWindow(SpritePtr pSprite, int x, int y)
 {
-    WindowPtr pWin;
-    BoxRec box;
+    ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
 
-    pSprite->spriteTraceGood = 1;       /* root window still there */
-    pWin = RootWindow(pSprite)->firstChild;
-    while (pWin) {
-        if ((pWin->mapped) &&
-            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
-            (x < pWin->drawable.x + (int) pWin->drawable.width +
-             wBorderWidth(pWin)) &&
-            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
-            (y < pWin->drawable.y + (int) pWin->drawable.height +
-             wBorderWidth(pWin))
-            /* When a window is shaped, a further check
-             * is made to see if the point is inside
-             * borderSize
-             */
-            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
-            && (!wInputShape(pWin) ||
-                RegionContainsPoint(wInputShape(pWin),
-                                    x - pWin->drawable.x,
-                                    y - pWin->drawable.y, &box))
-#ifdef ROOTLESS
-            /* In rootless mode windows may be offscreen, even when
-             * they're in X's stack. (E.g. if the native window system
-             * implements some form of virtual desktop system).
-             */
-            && !pWin->rootlessUnhittable
-#endif
-            ) {
-            if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
-                pSprite->spriteTraceSize += 10;
-                pSprite->spriteTrace = realloc(pSprite->spriteTrace,
-                                               pSprite->spriteTraceSize *
-                                               sizeof(WindowPtr));
-            }
-            pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
-            pWin = pWin->firstChild;
-        }
-        else
-            pWin = pWin->nextSib;
-    }
-    return DeepestSpriteWin(pSprite);
+    return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
 }
 
 /**
diff --git a/include/input.h b/include/input.h
index 36463f2..cbf949b 100644
--- a/include/input.h
+++ b/include/input.h
@@ -607,6 +607,7 @@ extern int GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type);
 void FixUpEventFromWindow(SpritePtr pSprite,
                           xEvent *xE,
                           WindowPtr pWin, Window child, Bool calcChild);
+extern Bool PointInBorderSize(WindowPtr pWin, int x, int y);
 extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y);
 extern int EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win);
 extern Bool ActivatePassiveGrab(DeviceIntPtr dev, GrabPtr grab,
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 86da789..5197c79 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -353,6 +353,9 @@ typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr);
 
 typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
 
+typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen,
+                                       SpritePtr pSprite, int x, int y);
+
 typedef struct _Screen {
     int myNum;                  /* index of this instance in Screens[] */
     ATOM id;
@@ -513,6 +516,7 @@ typedef struct _Screen {
     struct xorg_list offload_head;
 
     ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
+    XYToWindowProcPtr XYToWindow;
 } ScreenRec;
 
 static inline RegionPtr
diff --git a/mi/mi.h b/mi/mi.h
index 950ee38..1209a16 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -507,6 +507,10 @@ extern _X_EXPORT void miMarkUnrealizedWindow(WindowPtr /*pChild */ ,
 extern _X_EXPORT void miSegregateChildren(WindowPtr pWin, RegionPtr pReg,
                                           int depth);
 
+extern _X_EXPORT WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y);
+
+extern _X_EXPORT WindowPtr miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y);
+
 /* mizerarc.c */
 
 extern _X_EXPORT void miZeroPolyArc(DrawablePtr /*pDraw */ ,
diff --git a/mi/miscrinit.c b/mi/miscrinit.c
index 6aed52f..00c15f7 100644
--- a/mi/miscrinit.c
+++ b/mi/miscrinit.c
@@ -272,6 +272,7 @@ miScreenInit(ScreenPtr pScreen, void *pbits,  /* pointer to screen bits */
     pScreen->ChangeBorderWidth = miChangeBorderWidth;
     pScreen->SetShape = miSetShape;
     pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
+    pScreen->XYToWindow = miXYToWindow;
 
     miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
 
diff --git a/mi/miwindow.c b/mi/miwindow.c
index 697ffbc..951b8c5 100644
--- a/mi/miwindow.c
+++ b/mi/miwindow.c
@@ -57,6 +57,7 @@ SOFTWARE.
 #include "scrnintstr.h"
 #include "pixmapstr.h"
 #include "mivalidate.h"
+#include "inputstr.h"
 
 void
 miClearToBackground(WindowPtr pWin,
@@ -758,3 +759,68 @@ miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
             miSegregateChildren(pChild, pReg, depth);
     }
 }
+
+WindowPtr
+miSpriteTrace(SpritePtr pSprite, int x, int y)
+{
+    WindowPtr pWin;
+    BoxRec box;
+
+    pWin = DeepestSpriteWin(pSprite);
+    while (pWin) {
+        if ((pWin->mapped) &&
+            (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
+            (x < pWin->drawable.x + (int) pWin->drawable.width +
+             wBorderWidth(pWin)) &&
+            (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
+            (y < pWin->drawable.y + (int) pWin->drawable.height +
+             wBorderWidth(pWin))
+            /* When a window is shaped, a further check
+             * is made to see if the point is inside
+             * borderSize
+             */
+            && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+            && (!wInputShape(pWin) ||
+                RegionContainsPoint(wInputShape(pWin),
+                                    x - pWin->drawable.x,
+                                    y - pWin->drawable.y, &box))
+#ifdef ROOTLESS
+            /* In rootless mode windows may be offscreen, even when
+             * they're in X's stack. (E.g. if the native window system
+             * implements some form of virtual desktop system).
+             */
+            && !pWin->rootlessUnhittable
+#endif
+            ) {
+            if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) {
+                pSprite->spriteTraceSize += 10;
+                pSprite->spriteTrace = realloc(pSprite->spriteTrace,
+                                               pSprite->spriteTraceSize *
+                                               sizeof(WindowPtr));
+            }
+            pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+            pWin = pWin->firstChild;
+        }
+        else
+            pWin = pWin->nextSib;
+    }
+    return DeepestSpriteWin(pSprite);
+}
+
+/**
+ * Traversed from the root window to the window at the position x/y. While
+ * traversing, it sets up the traversal history in the spriteTrace array.
+ * After completing, the spriteTrace history is set in the following way:
+ *   spriteTrace[0] ... root window
+ *   spriteTrace[1] ... top level window that encloses x/y
+ *       ...
+ *   spriteTrace[spriteTraceGood - 1] ... window at x/y
+ *
+ * @returns the window at the given coordinates.
+ */
+WindowPtr
+miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y)
+{
+    pSprite->spriteTraceGood = 1;       /* root window still there */
+    return miSpriteTrace(pSprite, x, y);
+}
commit f37a46913489397d8628ffe578c8d4ed50b6ca72
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 26 12:24:49 2014 +0100

    configure: Change DEFAULT_LOGPREFIX to really be a filename prefix
    
    Rather then a full path prefix, this is a preparation patch for adding
    support for logging to another location when not running as root.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index f051414..bc643e8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2042,7 +2042,7 @@ if test "x$XORG" = xyes; then
 	XF86CONFIGDIR="xorg.conf.d"
 	AC_SUBST(XF86CONFIGDIR)
 	CONFIGFILE="$sysconfdir/$XF86CONFIGFILE"
-	LOGPREFIX="$logdir/Xorg."
+	LOGPREFIX="Xorg."
 	AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
 	AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
 	AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
@@ -2055,7 +2055,8 @@ if test "x$XORG" = xyes; then
 	AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory])
 	AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path])
 	AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path])
-	AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location])
+	AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location])
+	AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default logfile prefix])
 	AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
 	if test "x$VGAHW" = xyes; then
 		AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module])
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index 7df7a80..984c39b 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -143,7 +143,7 @@ const char *xf86ConfigFile = NULL;
 const char *xf86ConfigDir = NULL;
 const char *xf86ModulePath = DEFAULT_MODULE_PATH;
 MessageType xf86ModPathFrom = X_DEFAULT;
-const char *xf86LogFile = DEFAULT_LOGPREFIX;
+const char *xf86LogFile = DEFAULT_LOGDIR "/" DEFAULT_LOGPREFIX;
 MessageType xf86LogFileFrom = X_DEFAULT;
 Bool xf86LogFileWasOpened = FALSE;
 serverLayoutRec xf86ConfigLayout = { NULL, };
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 77a1aae..4e2a45b 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -45,7 +45,10 @@
 /* Path to installed libraries. */
 #undef DEFAULT_LIBRARY_PATH
 
-/* Path to server log file. */
+/* Default log location */
+#undef DEFAULT_LOGDIR
+
+/* Default logfile prefix */
 #undef DEFAULT_LOGPREFIX
 
 /* Building DRI-capable DDX. */
diff --git a/include/xwin-config.h.in b/include/xwin-config.h.in
index 176c019..a5e6b17 100644
--- a/include/xwin-config.h.in
+++ b/include/xwin-config.h.in
@@ -26,8 +26,5 @@
 /* Vendor web address for support */
 #undef __VENDORDWEBSUPPORT__
 
-/* Default log location */
-#undef DEFAULT_LOGDIR
-
 /* Whether we should re-locate the root to where the executable lives */
 #undef RELOCATE_PROJECTROOT
commit 9d20d18fb9dcc74bfa5392a2da40fd41b3e640d3
Merge: 8468e24 bc348bd
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 31 23:24:56 2014 -0700

    Merge remote-tracking branch 'jturney/master'

commit 8468e24430988058b150dc1daef3aad6ba9fa698
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Mar 27 11:48:39 2014 -0400

    mi: Hush extension initialization (#75870)
    
    Printing these as ErrorF is fairly obnoxious, since it means the
    non-hardware servers now spew stuff to the console for entirely routine
    events.  And actually, printing these at all is fairly obnoxious, since
    a) we're printing a line for every extension, whether it's enabled or
    not, and b) we're not actually initializing the extension at this point.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/mi/miinitext.c b/mi/miinitext.c
index 5b45ab4..1d90516 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -365,7 +365,6 @@ void
 LoadExtensionList(const ExtensionModule ext[], int size, Bool builtin)
 {
     ExtensionModule *newext;
-    const char *msg;
     int i;
 
     /* Make sure built-in extensions get added to the list before those
@@ -375,14 +374,7 @@ LoadExtensionList(const ExtensionModule ext[], int size, Bool builtin)
     if (!(newext = NewExtensionModuleList(size)))
         return;
 
-    if (builtin)
-        msg = "Initializing built-in";
-    else
-        msg = "Loading";
-
     for (i = 0; i < size; i++, newext++) {
-        ErrorF("%s extension %s\n", msg, ext[i].name);
-
         newext->name = ext[i].name;
         newext->initFunc = ext[i].initFunc;
         newext->disablePtr = ext[i].disablePtr;
commit a2880699e8f1f576e1a48ebf25e8982463323f84
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 25 08:21:16 2014 -0700

    fb: fix fast-path blt detection
    
    The width parameter is used to disable the blit fast-path (memcpy) when
    source and destination rows overlap in memory. This check was added in [0].
    
    Unfortunately, the calculation to determine if source and destination
    lines overlapped was incorrect:
      (1) it converts width from pixels to bytes, but width is actually in
          bits, not pixels.
      (2) it adds this byte offset to dst/srcLine, which implicitly converts
          the offset from bytes to sizeof(FbBits).
    
    Fix both of these by converting addresses to byte pointers and width
    to bytes and doing comparisons on the resulting byte address.
    
    For example:
    A 32-bpp 1366 pixel-wide row will have
      width = 1366 * 32 = 43712 bits
      bpp = 32
      (bpp >> 3) = 4
      width * (bpp >> 3) = 174848 FbBits
      (FbBits *)width => 699392 bytes
    
    So, "careful" was true if the destination line was within 699392 bytes,
    instead of just within its 1366 * 4 = 5464 byte row.
    
    This bug causes us to take the slow path for large non-overlapping rows
    that are "close" in memory.  As a data point, XGetImage(1366x768) on my
    ARM chromebook was taking ~140 ms, but with this fixed, it now takes
    about 60 ms.
      XGetImage() -> exaGetImage() -> fbGetImage -> fbBlt()
    
    [0] commit e32cc0b4c85c78cd8743a6e1680dcc79054b57ce
    Author: Adam Jackson <ajax at redhat.com>
    Date:   Thu Apr 21 16:37:11 2011 -0400
    
        fb: Fix memcpy abuse
    
        The memcpy fast path implicitly assumes that the copy walks
        left-to-right.  That's not something memcpy guarantees, and newer glibc
        on some processors will indeed break that assumption.  Since we walk a
        line at a time, check the source and destination against the width of
        the blit to determine whether we can be sloppy enough to allow memcpy.
        (Having done this, we can remove the check for !reverse as well.)
    
    v3: Convert to byte units
    
    This first checks to make sure the blt is byte aligned, converts all
    of the data to byte units and then compares for byte address range
    overlap between source and dest.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Daniel Kurtz <djkurtz at chromium.org>

diff --git a/fb/fbblt.c b/fb/fbblt.c
index 72a05f6..c615106 100644
--- a/fb/fbblt.c
+++ b/fb/fbblt.c
@@ -56,42 +56,48 @@ fbBlt(FbBits * srcLine,
     int n, nmiddle;
     Bool destInvarient;
     int startbyte, endbyte;
-    int careful;
 
     FbDeclareMergeRop();
 
+    if (alu == GXcopy && pm == FB_ALLONES &&
+        !(srcX & 7) && !(dstX & 7) && !(width & 7))
+    {
+        CARD8           *src_byte = (CARD8 *) srcLine + (srcX >> 3);
+        CARD8           *dst_byte = (CARD8 *) dstLine + (dstX >> 3);
+        FbStride        src_byte_stride = srcStride << (FB_SHIFT - 3);
+        FbStride        dst_byte_stride = dstStride << (FB_SHIFT - 3);
+        int             width_byte = (width >> 3);
+
+        /* Make sure there's no overlap; we can't use memcpy in that
+         * case as it's not well defined, so fall through to the
+         * general code
+         */
+        if (src_byte + width_byte <= dst_byte ||
+            dst_byte + width_byte <= src_byte)
+        {
+            int i;
+
+            if (!upsidedown)
+                for (i = 0; i < height; i++)
+                    MEMCPY_WRAPPED(dst_byte + i * dst_byte_stride,
+                                   src_byte + i * src_byte_stride,
+                                   width_byte);
+            else
+                for (i = height - 1; i >= 0; i--)
+                    MEMCPY_WRAPPED(dst_byte + i * dst_byte_stride,
+                                   src_byte + i * src_byte_stride,
+                                   width_byte);
+
+            return;
+        }
+    }
+
     if (bpp == 24 && !FbCheck24Pix(pm)) {
         fbBlt24(srcLine, srcStride, srcX, dstLine, dstStride, dstX,
                 width, height, alu, pm, reverse, upsidedown);
         return;
     }
 
-    careful = !((srcLine < dstLine && srcLine + width * (bpp >> 3) > dstLine) ||
-                (dstLine < srcLine && dstLine + width * (bpp >> 3) > srcLine))
-        || (bpp & 7);
-
-    if (alu == GXcopy && pm == FB_ALLONES && !careful &&
-        !(srcX & 7) && !(dstX & 7) && !(width & 7)) {
-        int i;
-        CARD8 *tmpsrc = (CARD8 *) srcLine;
-        CARD8 *tmpdst = (CARD8 *) dstLine;
-
-        srcStride *= sizeof(FbBits);
-        dstStride *= sizeof(FbBits);
-        width >>= 3;
-        tmpsrc += (srcX >> 3);
-        tmpdst += (dstX >> 3);
-
-        if (!upsidedown)
-            for (i = 0; i < height; i++)
-                MEMCPY_WRAPPED(tmpdst + i * dstStride, tmpsrc + i * srcStride, width);
-        else
-            for (i = height - 1; i >= 0; i--)
-                MEMCPY_WRAPPED(tmpdst + i * dstStride, tmpsrc + i * srcStride, width);
-
-        return;
-    }
-
     FbInitializeMergeRop(alu, pm);
     destInvarient = FbDestInvarientMergeRop();
     if (upsidedown) {
commit bc348bd2c42f3f18786085ccef2f010eff5bf3d2
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Mar 11 14:34:32 2013 +0000

    Handle -displayfd and an explicit display number sensibly
    
    Handle -displayfd and an explicit display number sensibly, e.g. use the
    explicitly specified display number, and write it to the displayfd
    
    v2: displayfd might be 0, so use -1 as invalid value
    v3: Rebase for addition of NoListenAll flag
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/dix/globals.c b/dix/globals.c
index 9738e9c..eaa2afe 100644
--- a/dix/globals.c
+++ b/dix/globals.c
@@ -127,7 +127,8 @@ int defaultColorVisualClass = -1;
 int monitorResolution = 0;
 
 const char *display;
-int displayfd;
+int displayfd = -1;
+Bool explicit_display = FALSE;
 char *ConnectionInfo;
 
 CARD32 TimeOutValue = DEFAULT_TIMEOUT * MILLI_PER_SECOND;
diff --git a/include/opaque.h b/include/opaque.h
index 7ec1d85..6b8071c 100644
--- a/include/opaque.h
+++ b/include/opaque.h
@@ -51,6 +51,7 @@ extern _X_EXPORT int defaultScreenSaverBlanking;
 extern _X_EXPORT int defaultScreenSaverAllowExposures;
 extern _X_EXPORT const char *display;
 extern _X_EXPORT int displayfd;
+extern _X_EXPORT Bool explicit_display;
 
 extern _X_EXPORT int defaultBackingStore;
 extern _X_EXPORT Bool disableBackingStore;
diff --git a/os/connection.c b/os/connection.c
index b3640b8..e914d9d 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -352,8 +352,8 @@ void
 NotifyParentProcess(void)
 {
 #if !defined(WIN32)
-    if (dynamic_display[0]) {
-        write(displayfd, dynamic_display, strlen(dynamic_display));
+    if (displayfd >= 0) {
+        write(displayfd, display, strlen(display));
         write(displayfd, "\n", 1);
         close(displayfd);
     }
@@ -405,18 +405,18 @@ CreateWellKnownSockets(void)
     FD_ZERO(&WellKnownConnections);
 
     /* display is initialized to "0" by main(). It is then set to the display
-     * number if specified on the command line, or to NULL when the -displayfd
-     * option is used. */
+     * number if specified on the command line. */
+
     if (NoListenAll) {
         ListenTransCount = 0;
     }
-    else if (display) {
+    else if ((displayfd < 0) || explicit_display) {
         if (TryCreateSocket(atoi(display), &partial) &&
             ListenTransCount >= 1)
             if (!PartialNetwork && partial)
                 FatalError ("Failed to establish all listening sockets");
     }
-    else { /* -displayfd */
+    else { /* -displayfd and no explicit display number */
         Bool found = 0;
         for (i = 0; i < 65535 - X_TCP_PORT; i++) {
             if (TryCreateSocket(i, &partial) && !partial) {
diff --git a/os/utils.c b/os/utils.c
index c513968..6e6974e 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -666,6 +666,7 @@ ProcessCommandLine(int argc, char *argv[])
         else if (argv[i][0] == ':') {
             /* initialize display */
             display = argv[i];
+            explicit_display = TRUE;
             display++;
             if (!VerifyDisplayName(display)) {
                 ErrorF("Bad display name: %s\n", display);
@@ -736,7 +737,6 @@ ProcessCommandLine(int argc, char *argv[])
         else if (strcmp(argv[i], "-displayfd") == 0) {
             if (++i < argc) {
                 displayfd = atoi(argv[i]);
-                display = NULL;
 #ifdef LOCK_SERVER
                 nolock = TRUE;
 #endif
commit a3730271d52542757ec0f41acc29e7730501f666
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Mar 24 17:32:10 2014 +0000

    Fix build when configured --enable-debug
    
    Include os.h for ErrorF() to fix implicit-function-declaration warnings when
    configured with --enable-debug.
    
    hw/xfree86/parser/DRI.c: In function 'xf86parseDRISection':
    hw/xfree86/parser/DRI.c:87:5: error: implicit declaration of function 'ErrorF' [-Werror=implicit-function-declaration]
    hw/xfree86/parser/Extensions.c: In function 'xf86parseExtensionsSection':
    hw/xfree86/parser/Extensions.c:77:5: error: implicit declaration of function 'ErrorF' [-Werror=implicit-function-declaration]
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Julien Cristau <jcristau at debian.org>

diff --git a/hw/xfree86/parser/DRI.c b/hw/xfree86/parser/DRI.c
index ad053f7..6be32d7 100644
--- a/hw/xfree86/parser/DRI.c
+++ b/hw/xfree86/parser/DRI.c
@@ -31,6 +31,7 @@
 #include <xorg-config.h>
 #endif
 
+#include "os.h"
 #include "xf86Parser.h"
 #include "xf86tokens.h"
 #include "Configint.h"
diff --git a/hw/xfree86/parser/Extensions.c b/hw/xfree86/parser/Extensions.c
index b5ba72e..a6fcb56 100644
--- a/hw/xfree86/parser/Extensions.c
+++ b/hw/xfree86/parser/Extensions.c
@@ -35,6 +35,7 @@
 #include <xorg-config.h>
 #endif
 
+#include "os.h"
 #include "xf86Parser.h"
 #include "xf86tokens.h"
 #include "Configint.h"
commit 5870bd398d6073938d821c060eccf24adc07a2f1
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Mar 24 17:32:09 2014 +0000

    Fix ephyr build with --disable-glamor
    
    See http://tinderbox.x.org/builds/2014-03-23-0010/logs/xserver/#build
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Tested-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Julien Cristau <jcristau at debian.org>

diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 4f48770..435919e 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -734,13 +734,16 @@ hostx_screen_init(KdScreenInfo *screen,
     scrpriv->win_width = width;
     scrpriv->win_height = height;
 
+#ifdef GLAMOR
     if (ephyr_glamor) {
         *bytes_per_line = 0;
         *bits_per_pixel = 0;
         ephyr_glamor_set_window_size(scrpriv->glamor,
                                      scrpriv->win_width, scrpriv->win_height);
         return NULL;
-    } else if (host_depth_matches_server(scrpriv)) {
+    } else
+#endif
+    if (host_depth_matches_server(scrpriv)) {
         *bytes_per_line = scrpriv->ximg->stride;
         *bits_per_pixel = scrpriv->ximg->bpp;
 
commit 432fc37e2ca833f1ec3cb614cbdc3a7ae13f22b7
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Feb 24 20:45:51 2014 +0000

    Build fbcmap_mi.c once, rather than once for each DDX
    
    Build fbcmap_mi.c once, rather than once for each DDX, and make it part of libfb
    or libwfb convenience library.
    
    Since 84e8de1271bb11b5b4b9747ae4647f47333a8ab7 we don't have fbcmap.c
    
    This is a sort of revert of 17d85387d1e6851d35474b65929e268ca64ef65b
    
    v2: Remove libkdrivestubs.la from configure.ac
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/configure.ac b/configure.ac
index a75ba8f..f589d6d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2408,8 +2408,7 @@ if test "$KDRIVE" = yes; then
 	    fi
 	    ;;
     esac
-    KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la'
-    KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB"
+    KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB"
     KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS"
     KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB"
     KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS $TSLIB_LIBS"
diff --git a/fb/Makefile.am b/fb/Makefile.am
index 89f3bab..752eabe 100644
--- a/fb/Makefile.am
+++ b/fb/Makefile.am
@@ -22,6 +22,7 @@ libfb_la_SOURCES = 	\
 	fbbits.h	\
 	fbblt.c		\
 	fbbltone.c	\
+	fbcmap_mi.c     \
 	fbcopy.c	\
 	fbfill.c	\
 	fbfillrect.c	\
@@ -50,5 +51,3 @@ libfb_la_SOURCES = 	\
 	fbwindow.c
 
 libwfb_la_SOURCES = $(libfb_la_SOURCES)
-
-EXTRA_DIST = fbcmap_mi.c
diff --git a/hw/dmx/Makefile.am b/hw/dmx/Makefile.am
index a05af13..eef84cb 100644
--- a/hw/dmx/Makefile.am
+++ b/hw/dmx/Makefile.am
@@ -65,7 +65,6 @@ Xdmx_SOURCES = dmx.c \
                dmxwindow.c \
                dmxwindow.h \
                $(top_srcdir)/mi/miinitext.c \
-               $(top_srcdir)/fb/fbcmap_mi.c \
                $(GLX_SRCS) 
 
 
diff --git a/hw/kdrive/src/Makefile.am b/hw/kdrive/src/Makefile.am
index 5799ddb..d69f0dd 100644
--- a/hw/kdrive/src/Makefile.am
+++ b/hw/kdrive/src/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = 					\
 
 AM_CFLAGS =	-DHAVE_DIX_CONFIG_H
 
-noinst_LTLIBRARIES = libkdrive.la libkdrivestubs.la
+noinst_LTLIBRARIES = libkdrive.la
 
 if XV
 KDRIVE_XV_SOURCES =	\
@@ -23,6 +23,3 @@ libkdrive_la_SOURCES =	\
 	kshadow.c	\
 	$(KDRIVE_XV_SOURCES) \
         $(top_srcdir)/mi/miinitext.c
-
-libkdrivestubs_la_SOURCES = \
-        $(top_srcdir)/fb/fbcmap_mi.c
diff --git a/hw/vfb/Makefile.am b/hw/vfb/Makefile.am
index a02a438..f0f9fee 100644
--- a/hw/vfb/Makefile.am
+++ b/hw/vfb/Makefile.am
@@ -1,7 +1,6 @@
 SUBDIRS = man
 
 bin_PROGRAMS = Xvfb
-noinst_LIBRARIES = libfbcmap.a
 
 AM_CFLAGS = -DHAVE_DIX_CONFIG_H \
             $(XVFBMODULES_CFLAGS) \
@@ -11,14 +10,10 @@ SRCS =	InitInput.c \
 	InitOutput.c \
 	$(top_srcdir)/mi/miinitext.c
 
-libfbcmap_a_CFLAGS = $(AM_CFLAGS)
-libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c
-
 Xvfb_SOURCES = $(SRCS)
 
 XVFB_LIBS = \
         @XVFB_LIBS@ \
-	libfbcmap.a \
 	$(MAIN_LIB) \
 	$(XSERVER_LIBS) \
 	$(top_builddir)/Xext/libXextdpmsstubs.la \
diff --git a/hw/xfree86/dixmods/Makefile.am b/hw/xfree86/dixmods/Makefile.am
index 3c43640..dd076e4 100644
--- a/hw/xfree86/dixmods/Makefile.am
+++ b/hw/xfree86/dixmods/Makefile.am
@@ -19,12 +19,12 @@ AM_CPPFLAGS = @XORG_INCS@ \
 
 libfb_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
 libfb_la_LIBADD = $(top_builddir)/fb/libfb.la
-libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c
+libfb_la_SOURCES = fbmodule.c
 libfb_la_CFLAGS = $(AM_CFLAGS)
 
 libwfb_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
 libwfb_la_LIBADD = $(top_builddir)/fb/libwfb.la
-libwfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c
+libwfb_la_SOURCES = fbmodule.c
 libwfb_la_CFLAGS = $(AM_CFLAGS) -DFB_ACCESS_WRAPPER
 
 libglx_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG)
diff --git a/hw/xnest/Makefile.am b/hw/xnest/Makefile.am
index bb8d3d8..eb550c0 100644
--- a/hw/xnest/Makefile.am
+++ b/hw/xnest/Makefile.am
@@ -1,7 +1,6 @@
 SUBDIRS = man
 
 bin_PROGRAMS = Xnest
-noinst_LIBRARIES = libfbcmap.a
 
 AM_CFLAGS = -DHAVE_XNEST_CONFIG_H \
             $(DIX_CFLAGS) \
@@ -44,12 +43,8 @@ SRCS =	Args.c \
 	xnest-config.h \
 	$(top_srcdir)/mi/miinitext.c
 
-libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c
-libfbcmap_a_CFLAGS = $(AM_CFLAGS)
-
 XNEST_LIBS = \
         @XNEST_LIBS@ \
-	libfbcmap.a \
 	$(top_builddir)/Xext/libXextdpmsstubs.la \
 	$(top_builddir)/Xi/libXistubs.la
 
diff --git a/hw/xquartz/Makefile.am b/hw/xquartz/Makefile.am
index 2ca953c..4da896d 100644
--- a/hw/xquartz/Makefile.am
+++ b/hw/xquartz/Makefile.am
@@ -20,7 +20,6 @@ SUBDIRS = bundle . $(GL_DIR) xpr pbproxy mach-startup man
 DIST_SUBDIRS = bundle . GL xpr pbproxy mach-startup man
 
 libXquartz_la_SOURCES = \
-	$(top_srcdir)/fb/fbcmap_mi.c \
 	$(top_srcdir)/mi/miinitext.c \
 	X11Application.m \
 	X11Controller.m \
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index b0da704..cf42cfd 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -128,7 +128,6 @@ SRCS =	InitInput.c \
 	winwindow.h \
 	XWin.rc \
 	$(top_srcdir)/mi/miinitext.c \
-	$(top_srcdir)/fb/fbcmap_mi.c \
 	$(SRCS_CLIPBOARD) \
 	$(SRCS_MULTIWINDOW) \
 	$(SRCS_MULTIWINDOWEXTWM) \
commit f23dd02b969089b66685f70887f19041049f7a24
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Fri Feb 21 18:11:33 2014 +0000

    Build Xi/stubs.c once as a convenience library, rather than once for each DDX which wants to use it
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index af85bd0..6c456c4 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -1,4 +1,4 @@
-noinst_LTLIBRARIES = libXi.la
+noinst_LTLIBRARIES = libXi.la libXistubs.la
 
 AM_CFLAGS = $(DIX_CFLAGS)
 
@@ -107,4 +107,5 @@ libXi_la_SOURCES =	\
 	xiwarppointer.c \
 	xiwarppointer.h
 
-EXTRA_DIST = stubs.c
+libXistubs_la_SOURCES =	\
+	stubs.c
diff --git a/hw/vfb/Makefile.am b/hw/vfb/Makefile.am
index c9f6957..a02a438 100644
--- a/hw/vfb/Makefile.am
+++ b/hw/vfb/Makefile.am
@@ -9,7 +9,6 @@ AM_CFLAGS = -DHAVE_DIX_CONFIG_H \
 
 SRCS =	InitInput.c \
 	InitOutput.c \
-	$(top_srcdir)/Xi/stubs.c \
 	$(top_srcdir)/mi/miinitext.c
 
 libfbcmap_a_CFLAGS = $(AM_CFLAGS)
@@ -22,7 +21,8 @@ XVFB_LIBS = \
 	libfbcmap.a \
 	$(MAIN_LIB) \
 	$(XSERVER_LIBS) \
-	$(top_builddir)/Xext/libXextdpmsstubs.la
+	$(top_builddir)/Xext/libXextdpmsstubs.la \
+	$(top_builddir)/Xi/libXistubs.la
 
 Xvfb_LDADD = $(XVFB_LIBS) $(XVFB_SYS_LIBS) $(XSERVER_SYS_LIBS)
 Xvfb_DEPENDENCIES = $(XVFB_LIBS)
diff --git a/hw/xnest/Makefile.am b/hw/xnest/Makefile.am
index c5560fd..bb8d3d8 100644
--- a/hw/xnest/Makefile.am
+++ b/hw/xnest/Makefile.am
@@ -42,7 +42,6 @@ SRCS =	Args.c \
 	XNPixmap.h \
 	XNWindow.h \
 	xnest-config.h \
-	$(top_srcdir)/Xi/stubs.c \
 	$(top_srcdir)/mi/miinitext.c
 
 libfbcmap_a_SOURCES = $(top_srcdir)/fb/fbcmap_mi.c
@@ -51,7 +50,8 @@ libfbcmap_a_CFLAGS = $(AM_CFLAGS)
 XNEST_LIBS = \
         @XNEST_LIBS@ \
 	libfbcmap.a \
-	$(top_builddir)/Xext/libXextdpmsstubs.la
+	$(top_builddir)/Xext/libXextdpmsstubs.la \
+	$(top_builddir)/Xi/libXistubs.la
 
 Xnest_SOURCES = $(SRCS)
 
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 6668045..b0da704 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -127,7 +127,6 @@ SRCS =	InitInput.c \
 	winresource.h \
 	winwindow.h \
 	XWin.rc \
-	$(top_srcdir)/Xi/stubs.c \
 	$(top_srcdir)/mi/miinitext.c \
 	$(top_srcdir)/fb/fbcmap_mi.c \
 	$(SRCS_CLIPBOARD) \
@@ -153,7 +152,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless
 
 XWIN_SYS_LIBS += -ldxguid
 XWIN_LIBS += 	$(top_builddir)/pseudoramiX/libPseudoramiX.la \
-                $(top_builddir)/Xext/libXextdpmsstubs.la
+                $(top_builddir)/Xext/libXextdpmsstubs.la \
+                $(top_builddir)/Xi/libXistubs.la
 XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS)
 XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS)
 XWin_LDFLAGS = -mwindows -static -Wl,--disable-stdcall-fixup
diff --git a/test/Makefile.am b/test/Makefile.am
index 7209fbd..3ad24d9 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -70,8 +70,7 @@ endif
 else
 nodist_libxservertest_la_SOURCES = \
             ddxstubs.c \
-            $(top_srcdir)/mi/miinitext.c \
-            $(top_srcdir)/Xi/stubs.c
+            $(top_srcdir)/mi/miinitext.c
 
 libxservertest_la_LIBADD += \
             $(top_builddir)/damageext/libdamageext.la \
@@ -84,6 +83,7 @@ libxservertest_la_LIBADD += \
             $(top_builddir)/Xext/libXext.la \
             $(top_builddir)/Xext/libXextdpmsstubs.la \
             $(top_builddir)/Xi/libXi.la \
+            $(top_builddir)/Xi/libXistubs.la \
             $(top_builddir)/xfixes/libxfixes.la \
             $(top_builddir)/xkb/libxkb.la \
             $(top_builddir)/xkb/libxkbstubs.la
commit 45b223e1c2bdc447263a9de7af62c93f4058c33c
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Sep 7 12:50:20 2011 +0100

    Build dpmsstubs.c once as a convenience library, rather than once for each DDX which wants to use it
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index 8e31f13..a9a4468 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -1,4 +1,4 @@
-noinst_LTLIBRARIES = libXext.la
+noinst_LTLIBRARIES = libXext.la libXextdpmsstubs.la
 
 AM_CFLAGS = $(DIX_CFLAGS)
 
@@ -96,6 +96,8 @@ endif
 libXext_la_SOURCES =		$(BUILTIN_SRCS)
 libXext_la_LIBADD =		$(BUILTIN_LIBS)
 
+libXextdpmsstubs_la_SOURCES = dpmsstubs.c
+
 EXTRA_DIST = \
 	$(MITSHM_SRCS) \
 	$(XV_SRCS) \
diff --git a/hw/vfb/Makefile.am b/hw/vfb/Makefile.am
index 9f4992c..c9f6957 100644
--- a/hw/vfb/Makefile.am
+++ b/hw/vfb/Makefile.am
@@ -9,7 +9,6 @@ AM_CFLAGS = -DHAVE_DIX_CONFIG_H \
 
 SRCS =	InitInput.c \
 	InitOutput.c \
-	$(top_srcdir)/Xext/dpmsstubs.c \
 	$(top_srcdir)/Xi/stubs.c \
 	$(top_srcdir)/mi/miinitext.c
 
@@ -22,7 +21,8 @@ XVFB_LIBS = \
         @XVFB_LIBS@ \
 	libfbcmap.a \
 	$(MAIN_LIB) \
-	$(XSERVER_LIBS)
+	$(XSERVER_LIBS) \
+	$(top_builddir)/Xext/libXextdpmsstubs.la
 
 Xvfb_LDADD = $(XVFB_LIBS) $(XVFB_SYS_LIBS) $(XSERVER_SYS_LIBS)
 Xvfb_DEPENDENCIES = $(XVFB_LIBS)
diff --git a/hw/xnest/Makefile.am b/hw/xnest/Makefile.am
index 3c099cd..c5560fd 100644
--- a/hw/xnest/Makefile.am
+++ b/hw/xnest/Makefile.am
@@ -42,7 +42,6 @@ SRCS =	Args.c \
 	XNPixmap.h \
 	XNWindow.h \
 	xnest-config.h \
-	$(top_srcdir)/Xext/dpmsstubs.c \
 	$(top_srcdir)/Xi/stubs.c \
 	$(top_srcdir)/mi/miinitext.c
 
@@ -51,7 +50,8 @@ libfbcmap_a_CFLAGS = $(AM_CFLAGS)
 
 XNEST_LIBS = \
         @XNEST_LIBS@ \
-	libfbcmap.a
+	libfbcmap.a \
+	$(top_builddir)/Xext/libXextdpmsstubs.la
 
 Xnest_SOURCES = $(SRCS)
 
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 7f0eaf0..6668045 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -127,7 +127,6 @@ SRCS =	InitInput.c \
 	winresource.h \
 	winwindow.h \
 	XWin.rc \
-	$(top_srcdir)/Xext/dpmsstubs.c \
 	$(top_srcdir)/Xi/stubs.c \
 	$(top_srcdir)/mi/miinitext.c \
 	$(top_srcdir)/fb/fbcmap_mi.c \
@@ -153,12 +152,13 @@ XWin_SOURCES = $(SRCS)
 AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless
 
 XWIN_SYS_LIBS += -ldxguid
-XWIN_LIBS += 	$(top_builddir)/pseudoramiX/libPseudoramiX.la
-
+XWIN_LIBS += 	$(top_builddir)/pseudoramiX/libPseudoramiX.la \
+                $(top_builddir)/Xext/libXextdpmsstubs.la
 XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS)
 XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS)
 XWin_LDFLAGS = -mwindows -static -Wl,--disable-stdcall-fixup
 
+
 .rc.o:
 	$(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 88fb6aa..7209fbd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -71,7 +71,6 @@ else
 nodist_libxservertest_la_SOURCES = \
             ddxstubs.c \
             $(top_srcdir)/mi/miinitext.c \
-            $(top_srcdir)/Xext/dpmsstubs.c \
             $(top_srcdir)/Xi/stubs.c
 
 libxservertest_la_LIBADD += \
@@ -83,6 +82,7 @@ libxservertest_la_LIBADD += \
             $(top_builddir)/randr/librandr.la \
             $(top_builddir)/render/librender.la \
             $(top_builddir)/Xext/libXext.la \
+            $(top_builddir)/Xext/libXextdpmsstubs.la \
             $(top_builddir)/Xi/libXi.la \
             $(top_builddir)/xfixes/libxfixes.la \
             $(top_builddir)/xkb/libxkb.la \
commit 7b2a517ba99f6756e98c4aef47d9b9399b997157
Author: Julien Cristau <jcristau at debian.org>
Date:   Wed Mar 26 23:24:20 2014 +0100

    Xephyr: restore initial window resize lost in xcb conversion
    
    The XResizeWindow call wasn't replaced by the xcb equivalent, so we
    were no longer setting the initial window size, only wm size hints.
    
    Regression from commit a2b73da "Xephyr: start converting hostx.c over to
    xcb"
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=74849
    
    Signed-off-by: Julien Cristau <jcristau at debian.org>
    Reported-by: Laércio de Sousa <lbsousajr at gmail.com>
    Tested-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 3054f5f..4f48770 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -710,6 +710,12 @@ hostx_screen_init(KdScreenInfo *screen,
             malloc(scrpriv->ximg->stride * buffer_height);
     }
 
+    {
+        uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
+        uint32_t values[2] = {width, height};
+        xcb_configure_window(HostX.conn, scrpriv->win, mask, values);
+    }
+
     if (scrpriv->win_pre_existing == None && !EphyrWantResize) {
         /* Ask the WM to keep our size static */
         xcb_size_hints_t size_hints = {0};
commit 1b5d7e78460ed686ba2da398dab341d4867fd4a0
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 12 14:35:27 2014 -0700

    glamor: Add glamor_program PolyPoint implementation
    
    This accelerates poly point when possible by off-loading all geometry
    computation to the GPU.
    
    Improves x11perf -dot performance by 28109.5% +/- 1022.01% (n=3)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index eff769e..8555e40 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -32,7 +32,7 @@ libglamor_la_SOURCES = \
 	glamor_getimage.c\
 	glamor_copyplane.c\
 	glamor_glyphblt.c\
-	glamor_polyops.c\
+	glamor_points.c\
 	glamor_priv.h\
 	glamor_pixmap.c\
 	glamor_largepixmap.c\
diff --git a/glamor/glamor_points.c b/glamor/glamor_points.c
new file mode 100644
index 0000000..5399f96
--- /dev/null
+++ b/glamor/glamor_points.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2009 Intel Corporation
+ * Copyright © 1998 Keith Packard
+ *
+ * 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:
+ *    Zhigang Gong <zhigang.gong at linux.intel.com>
+ *
+ */
+
+#include "glamor_priv.h"
+#include "glamor_transform.h"
+
+static const glamor_facet glamor_facet_point = {
+    .name = "poly_point",
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = GLAMOR_POS(gl_Position, primitive),
+};
+
+Bool
+glamor_poly_point_nf(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPointPtr ppt)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_program *prog = &glamor_priv->point_prog;
+    glamor_pixmap_private *pixmap_priv;
+    int off_x, off_y;
+    GLshort *vbo_ppt;
+    char *vbo_offset;
+    int box_x, box_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    glamor_get_context(glamor_priv);
+
+    if (prog->failed)
+        goto bail_ctx;
+
+    if (!prog->prog) {
+        if (!glamor_build_program(screen, prog,
+                                  &glamor_facet_point,
+                                  &glamor_fill_solid))
+            goto bail_ctx;
+    }
+
+    if (!glamor_use_program(pixmap, gc, prog, NULL))
+        goto bail_ctx;
+
+    vbo_ppt = glamor_get_vbo_space(screen, npt * (2 * sizeof (INT16)), &vbo_offset);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE, 0, vbo_offset);
+    if (mode == CoordModePrevious) {
+        int n = npt;
+        INT16 x = 0, y = 0;
+        while (n--) {
+            vbo_ppt[0] = (x += ppt->x);
+            vbo_ppt[1] = (y += ppt->y);
+            vbo_ppt += 2;
+            ppt++;
+        }
+    } else
+        memcpy(vbo_ppt, ppt, npt * (2 * sizeof (INT16)));
+    glamor_put_vbo_space(screen);
+
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int nbox = RegionNumRects(gc->pCompositeClip);
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE, prog->matrix_uniform, &off_x, &off_y);
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            glDrawArrays(GL_POINTS, 0, npt);
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    glamor_put_context(glamor_priv);
+
+    glamor_priv->state = RENDER_STATE;
+    glamor_priv->render_idle_cnt = 0;
+
+    return TRUE;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    glamor_put_context(glamor_priv);
+bail:
+    return FALSE;
+}
+
+void
+glamor_poly_point(DrawablePtr drawable, GCPtr gc, int mode, int npt,
+                  DDXPointPtr ppt)
+{
+    if (glamor_poly_point_nf(drawable, gc, mode, npt, ppt))
+        return;
+    miPolyPoint(drawable, gc, mode, npt, ppt);
+}
diff --git a/glamor/glamor_polyops.c b/glamor/glamor_polyops.c
deleted file mode 100644
index f4036a0..0000000
--- a/glamor/glamor_polyops.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * 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:
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- *
- */
-
-#include "glamor_priv.h"
-
-static Bool
-_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
-                   DDXPointPtr ppt, Bool fallback)
-{
-    if (!fallback && glamor_ddx_fallback_check_gc(pGC)
-        && glamor_ddx_fallback_check_pixmap(pDrawable))
-        return FALSE;
-
-    miPolyPoint(pDrawable, pGC, mode, npt, ppt);
-
-    return TRUE;
-}
-
-void
-glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
-                  DDXPointPtr ppt)
-{
-    _glamor_poly_point(pDrawable, pGC, mode, npt, ppt, TRUE);
-}
-
-Bool
-glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
-                     DDXPointPtr ppt)
-{
-    return _glamor_poly_point(pDrawable, pGC, mode, npt, ppt, FALSE);
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 164d581..4c305ab 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -220,6 +220,9 @@ typedef struct glamor_screen_private {
     GLint solid_prog;
     GLint solid_color_uniform_location;
 
+    /* glamor point shader */
+    glamor_program point_prog;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
commit 72a4beff6d3aed767df9a30bca0c1d860715928f
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 22 15:20:49 2014 -0700

    glamor: Move glamor_poly_segment to separate glamor_segment.c file
    
    There's no reason to mix PolyPoint and PolySegment in the same file.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index dec6467..eff769e 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -20,6 +20,7 @@ libglamor_la_SOURCES = \
 	glamor_polylines.c \
 	glamor_putimage.c \
 	glamor_setspans.c \
+	glamor_segment.c \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_program.c \
diff --git a/glamor/glamor_polyops.c b/glamor/glamor_polyops.c
index 1484d80..f4036a0 100644
--- a/glamor/glamor_polyops.c
+++ b/glamor/glamor_polyops.c
@@ -54,29 +54,3 @@ glamor_poly_point_nf(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
 {
     return _glamor_poly_point(pDrawable, pGC, mode, npt, ppt, FALSE);
 }
-
-static Bool
-_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
-                     xSegment *pSeg, Bool fallback)
-{
-    if (!fallback && glamor_ddx_fallback_check_gc(pGC)
-        && glamor_ddx_fallback_check_pixmap(pDrawable))
-        return FALSE;
-
-    miPolySegment(pDrawable, pGC, nseg, pSeg);
-
-    return TRUE;
-}
-
-void
-glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg)
-{
-    _glamor_poly_segment(pDrawable, pGC, nseg, pSeg, TRUE);
-}
-
-Bool
-glamor_poly_segment_nf(DrawablePtr pDrawable, GCPtr pGC, int nseg,
-                       xSegment *pSeg)
-{
-    return _glamor_poly_segment(pDrawable, pGC, nseg, pSeg, FALSE);
-}
diff --git a/glamor/glamor_segment.c b/glamor/glamor_segment.c
new file mode 100644
index 0000000..84b27ac
--- /dev/null
+++ b/glamor/glamor_segment.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+
+Bool
+glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc, int nseg,
+                       xSegment *seg)
+{
+    return FALSE;
+}
+
+void
+glamor_poly_segment(DrawablePtr drawable, GCPtr gc, int nseg,
+                    xSegment *seg)
+{
+    if (glamor_poly_segment_nf(drawable, gc, nseg, seg))
+        return;
+    miPolySegment(drawable, gc, nseg, seg);
+}
commit 029b64c30a8bdf87edfdb1c988f4e8dcee1bb4ef
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 12 14:27:59 2014 -0700

    glamor: Add infrastructure for generating shaders on the fly
    
    This just adds a bunch of support code to construct shaders from
    'facets', which bundle attributes needed for each layer of the
    rendering system. At this point, that includes only the primitive and
    the fill stuff.
    
    v2: Correct comment in glamor transform about 1/2 pixel correction needed
        for GL_POINT. (Eric Anholt)
    v3: Rebase on Markus's cleanups (change by anholt)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index ffc8c23..dec6467 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -22,6 +22,8 @@ libglamor_la_SOURCES = \
 	glamor_setspans.c \
 	glamor_render.c \
 	glamor_gradient.c \
+	glamor_program.c \
+	glamor_transform.c \
 	glamor_trapezoid.c \
 	glamor_tile.c \
 	glamor_triangles.c\
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index ed2c767..164d581 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -52,6 +52,7 @@
 
 #include "glamor_debug.h"
 #include "glamor_context.h"
+#include "glamor_program.h"
 
 #include <list.h>
 
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
new file mode 100644
index 0000000..e2e1434
--- /dev/null
+++ b/glamor/glamor_program.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_transform.h"
+#include "glamor_program.h"
+
+static Bool
+use_solid(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
+{
+    return glamor_set_solid(pixmap, gc, TRUE, prog->fg_uniform);
+}
+
+const glamor_facet glamor_fill_solid = {
+    .name = "solid",
+    .fs_exec = "       gl_FragColor = fg;\n",
+    .locations = glamor_program_location_fg,
+    .use = use_solid,
+};
+
+static Bool
+use_tile(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
+{
+    return glamor_set_tiled(pixmap, gc, prog->fill_offset_uniform, prog->fill_size_uniform);
+}
+
+static const glamor_facet glamor_fill_tile = {
+    .name = "tile",
+    .version = 130,
+    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + pos;\n",
+    .fs_exec =  "       gl_FragColor = texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0);\n",
+    .locations = glamor_program_location_fill,
+    .use = use_tile,
+};
+
+#if 0
+static Bool
+use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog)
+{
+    return glamor_set_stippled(pixmap, gc, prog->fg_uniform, prog->fill_offset_uniform, prog->fill_size_uniform);
+}
+
+static const glamor_facet glamor_fill_stipple = {
+    .name = "stipple",
+    .version = 130,
+    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + pos;\n";
+    .fs_exec = ("       if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
+                "               discard;\n"
+                "       gl_FragColor = fg;\n")
+    .locations = glamor_program_location_fg | glamor_program_location_fill
+    .use = use_stipple,
+};
+
+static const glamor_facet glamor_fill_opaque_stipple = {
+    .name = "opaque_stipple",
+    .version = 130,
+    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + pos;\n";
+    .fs_exec = ("       if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
+                "               gl_FragColor = bg;\n"
+                "       else\n"
+                "               gl_FragColor = fg;\n"),
+    .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill
+    .use = use_opaque_stipple
+};
+#endif
+
+static const glamor_facet *glamor_facet_fill[4] = {
+    &glamor_fill_solid,
+    &glamor_fill_tile,
+    NULL,
+    NULL,
+};
+
+typedef struct {
+    glamor_program_location     location;
+    const char                  *vs_vars;
+    const char                  *fs_vars;
+} glamor_location_var;
+
+static glamor_location_var location_vars[] = {
+    {
+        .location = glamor_program_location_fg,
+        .fs_vars = "uniform vec4 fg;\n"
+    },
+    {
+        .location = glamor_program_location_bg,
+        .fs_vars = "uniform vec4 bg;\n"
+    },
+    {
+        .location = glamor_program_location_fill,
+        .vs_vars = ("uniform vec2 fill_offset;\n"
+                    "varying vec2 fill_pos;\n"),
+        .fs_vars = ("uniform sampler2D sampler;\n"
+                    "uniform vec2 fill_size;\n"
+                    "varying vec2 fill_pos;\n")
+    },
+    {
+        .location = glamor_program_location_font,
+        .fs_vars = "uniform usampler2D font;\n",
+    },
+};
+
+#define NUM_LOCATION_VARS       (sizeof location_vars / sizeof location_vars[0])
+
+static char *
+add_var(char *cur, const char *add)
+{
+    char *new;
+
+    if (!add)
+        return cur;
+
+    new = realloc(cur, strlen(cur) + strlen(add) + 1);
+    if (!new) {
+        free(cur);
+        return NULL;
+    }
+    strcat(new, add);
+    return new;
+}
+
+static char *
+vs_location_vars(glamor_program_location locations)
+{
+    int l;
+    char *vars = strdup("");
+
+    for (l = 0; vars && l < NUM_LOCATION_VARS; l++)
+        if (locations & location_vars[l].location)
+            vars = add_var(vars, location_vars[l].vs_vars);
+    return vars;
+}
+
+static char *
+fs_location_vars(glamor_program_location locations)
+{
+    int l;
+    char *vars = strdup("");
+
+    for (l = 0; vars && l < NUM_LOCATION_VARS; l++)
+        if (locations & location_vars[l].location)
+            vars = add_var(vars, location_vars[l].fs_vars);
+    return vars;
+}
+
+static const char vs_template[] =
+    "%s"                                /* version */
+    "%s"                                /* prim vs_vars */
+    "%s"                                /* fill vs_vars */
+    "%s"                                /* location vs_vars */
+    GLAMOR_DECLARE_MATRIX
+    "void main() {\n"
+    "%s"                                /* prim vs_exec, outputs 'pos' and gl_Position */
+    "%s"                                /* fill vs_exec */
+    "}\n";
+
+static const char fs_template[] =
+    "%s"                                /* version */
+    GLAMOR_DEFAULT_PRECISION
+    "%s"                                /* prim fs_vars */
+    "%s"                                /* fill fs_vars */
+    "%s"                                /* location fs_vars */
+    "void main() {\n"
+    "%s"                                /* prim fs_exec */
+    "%s"                                /* fill fs_exec */
+    "}\n";
+
+static const char *
+str(const char *s)
+{
+    if (!s)
+        return "";
+    return s;
+}
+
+static const glamor_facet facet_null_fill = {
+    .name = ""
+};
+
+static GLint
+glamor_get_uniform(glamor_program               *prog,
+                   glamor_program_location      location,
+                   const char                   *name)
+{
+    GLint uniform;
+    if (location && (prog->locations & location) == 0)
+        return -2;
+    uniform = glGetUniformLocation(prog->prog, name);
+#if DBG
+    ErrorF("%s uniform %d\n", name, uniform);
+#endif
+    return uniform;
+}
+
+Bool
+glamor_build_program(ScreenPtr          screen,
+                     glamor_program     *prog,
+                     const glamor_facet *prim,
+                     const glamor_facet *fill)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_program_location     locations = prim->locations;
+    glamor_program_flag         flags = prim->flags;
+
+    int                         version = prim->version;
+    char                        *version_string = NULL;
+
+    char                        *fs_vars = NULL;
+    char                        *vs_vars = NULL;
+
+    char                        *vs_prog_string;
+    char                        *fs_prog_string;
+
+    GLint                       fs_prog, vs_prog;
+
+    if (!fill)
+        fill = &facet_null_fill;
+
+    locations |= fill->locations;
+    flags |= fill->flags;
+    version = MAX(version, fill->version);
+
+    if (version >= 130) {
+
+        /* Would be nice to have a cleaner test for GLSL 1.30 support,
+         * but for now this should suffice
+         */
+        if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP ||
+            epoxy_gl_version() < 30) {
+            goto fail;
+        }
+    }
+
+    vs_vars = vs_location_vars(locations);
+    fs_vars = fs_location_vars(locations);
+
+    if (!vs_vars)
+        goto fail;
+    if (!fs_vars)
+        goto fail;
+
+    if (version) {
+        if (asprintf(&version_string, "#version %d\n", version) < 0)
+            version_string = NULL;
+        if (!version_string)
+            goto fail;
+    }
+
+    if (asprintf(&vs_prog_string,
+                 vs_template,
+                 str(version_string),
+                 str(prim->vs_vars),
+                 str(fill->vs_vars),
+                 vs_vars,
+                 str(prim->vs_exec),
+                 str(fill->vs_exec)) < 0)
+        vs_prog_string = NULL;
+
+    if (asprintf(&fs_prog_string,
+                 fs_template,
+                 str(version_string),
+                 str(prim->fs_vars),
+                 str(fill->fs_vars),
+                 fs_vars,
+                 str(prim->fs_exec),
+                 str(fill->fs_exec)) < 0)
+        fs_prog_string = NULL;
+
+    if (!vs_prog_string || !fs_prog_string)
+        goto fail;
+
+#define DBG 0
+#if DBG
+    ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s",
+           prim->name, fill->name, vs_prog_string, fs_prog_string);
+#endif
+
+    prog->prog = glCreateProgram();
+    prog->flags = flags;
+    prog->locations = locations;
+    prog->prim_use = prim->use;
+    prog->fill_use = fill->use;
+
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string);
+    free(vs_prog_string);
+    free(fs_prog_string);
+    glAttachShader(prog->prog, vs_prog);
+    glDeleteShader(vs_prog);
+    glAttachShader(prog->prog, fs_prog);
+    glDeleteShader(fs_prog);
+    glBindAttribLocation(prog->prog, GLAMOR_VERTEX_POS, "primitive");
+
+    if (prim->source_name) {
+#if DBG
+        ErrorF("Bind GLAMOR_VERTEX_SOURCE to %s\n", prim->source_name);
+#endif
+        glBindAttribLocation(prog->prog, GLAMOR_VERTEX_SOURCE, prim->source_name);
+    }
+
+    glamor_link_glsl_prog(screen, prog->prog, "%s_%s", prim->name, fill->name);
+
+    prog->matrix_uniform = glamor_get_uniform(prog, glamor_program_location_none, "v_matrix");
+    prog->fg_uniform = glamor_get_uniform(prog, glamor_program_location_fg, "fg");
+    prog->bg_uniform = glamor_get_uniform(prog, glamor_program_location_bg, "bg");
+    prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_offset");
+    prog->fill_size_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_size");
+    prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
+
+    if (glGetError() != GL_NO_ERROR)
+        goto fail;
+
+    free(version_string);
+    free(fs_vars);
+    free(vs_vars);
+    return TRUE;
+fail:
+    prog->failed = 1;
+    if (prog->prog) {
+        glDeleteProgram(prog->prog);
+        prog->prog = 0;
+    }
+    free(version_string);
+    free(fs_vars);
+    free(vs_vars);
+    return FALSE;
+}
+
+Bool
+glamor_use_program(PixmapPtr            pixmap,
+                   GCPtr                gc,
+                   glamor_program       *prog,
+                   void                 *arg)
+{
+    glUseProgram(prog->prog);
+
+    if (prog->prim_use && !prog->prim_use(pixmap, gc, prog, arg))
+        return FALSE;
+
+    if (prog->fill_use && !prog->fill_use(pixmap, gc, prog, arg))
+        return FALSE;
+
+    return TRUE;
+}
+
+glamor_program *
+glamor_use_program_fill(PixmapPtr               pixmap,
+                        GCPtr                   gc,
+                        glamor_program_fill     *program_fill,
+                        const glamor_facet      *prim)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    glamor_program              *prog = &program_fill->progs[gc->fillStyle];
+
+    int                         fill_style = gc->fillStyle;
+    const glamor_facet          *fill;
+
+    if (prog->failed)
+        return FALSE;
+
+    if (!prog->prog) {
+        fill = glamor_facet_fill[fill_style];
+        if (!fill)
+            return NULL;
+
+        if (!glamor_build_program(screen, prog, prim, fill))
+            return NULL;
+    }
+
+    if (!glamor_use_program(pixmap, gc, prog, NULL))
+        return NULL;
+
+    return prog;
+}
diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
new file mode 100644
index 0000000..88efc35
--- /dev/null
+++ b/glamor/glamor_program.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _GLAMOR_PROGRAM_H_
+#define _GLAMOR_PROGRAM_H_
+
+typedef enum {
+    glamor_program_location_none = 0,
+    glamor_program_location_fg = 1,
+    glamor_program_location_bg = 2,
+    glamor_program_location_fill = 4,
+    glamor_program_location_font = 8,
+} glamor_program_location;
+
+typedef enum {
+    glamor_program_flag_none = 0,
+} glamor_program_flag;
+
+typedef struct _glamor_program glamor_program;
+
+typedef Bool (*glamor_use) (PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg);
+
+typedef struct {
+    const char                          *name;
+    const int                           version;
+    const char                          *vs_vars;
+    const char                          *vs_exec;
+    const char                          *fs_vars;
+    const char                          *fs_exec;
+    const glamor_program_location       locations;
+    const glamor_program_flag           flags;
+    const char                          *source_name;
+    glamor_use                          use;
+} glamor_facet;
+
+struct _glamor_program {
+    GLint                       prog;
+    GLint                       failed;
+    GLint                       matrix_uniform;
+    GLint                       fg_uniform;
+    GLint                       bg_uniform;
+    GLint                       fill_size_uniform;
+    GLint                       fill_offset_uniform;
+    GLint                       font_uniform;
+    glamor_program_location     locations;
+    glamor_program_flag         flags;
+    glamor_use                  prim_use;
+    glamor_use                  fill_use;
+};
+
+typedef struct {
+    glamor_program      progs[4];
+} glamor_program_fill;
+
+extern const glamor_facet glamor_fill_solid;
+
+Bool
+glamor_build_program(ScreenPtr          screen,
+                     glamor_program     *prog,
+                     const glamor_facet *prim,
+                     const glamor_facet *fill);
+
+Bool
+glamor_use_program(PixmapPtr            pixmap,
+                   GCPtr                gc,
+                   glamor_program       *prog,
+                   void                 *arg);
+
+glamor_program *
+glamor_use_program_fill(PixmapPtr               pixmap,
+                        GCPtr                   gc,
+                        glamor_program_fill     *program_fill,
+                        const glamor_facet      *prim);
+
+#endif /* _GLAMOR_PROGRAM_H_ */
diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
new file mode 100644
index 0000000..d6ba564
--- /dev/null
+++ b/glamor/glamor_transform.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_transform.h"
+
+
+/*
+ * Set up rendering to target the specified drawable, computing an
+ * appropriate transform for the vertex shader to convert
+ * drawable-relative coordinates into pixmap-relative coordinates. If
+ * requested, the offset from pixmap origin coordinates back to window
+ * system coordinates will be returned in *p_off_x, *p_off_y so that
+ * clipping computations can be adjusted as appropriate
+ */
+
+void
+glamor_set_destination_drawable(DrawablePtr     drawable,
+                                int             box_x,
+                                int             box_y,
+                                Bool            do_drawable_translate,
+                                Bool            center_offset,
+                                GLint           matrix_uniform_location,
+                                int             *p_off_x,
+                                int             *p_off_y)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    int off_x, off_y;
+    BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
+    int w = box->x2 - box->x1;
+    int h = box->y2 - box->y1;
+    float scale_x = 2.0f / (float) w;
+    float scale_y = 2.0f / (float) h;
+    float center_adjust = 0.0f;
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+    off_x -= box->x1;
+    off_y -= box->y1;
+
+    if (p_off_x) {
+        *p_off_x = off_x;
+        *p_off_y = off_y;
+    }
+
+    /* A tricky computation to find the right value for the two linear functions
+     * that transform rendering coordinates to pixmap coordinates
+     *
+     *  pixmap_x = render_x + drawable->x + off_x
+     *  pixmap_y = render_y + drawable->y + off_y
+     *
+     *  gl_x = pixmap_x * 2 / width - 1
+     *  gl_y = pixmap_y * 2 / height - 1
+     *
+     *  gl_x = (render_x + drawable->x + off_x) * 2 / width - 1
+     *
+     *  gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / width - 1
+     *
+     * I'll think about yInverted later, when I have some way to test
+     */
+
+    if (do_drawable_translate) {
+        off_x += drawable->x;
+        off_y += drawable->y;
+    }
+
+    /*
+     * To get GL_POINTS drawn in the right spot, we need to adjust the
+     * coordinates by 1/2 a pixel.
+     */
+    if (center_offset)
+        center_adjust = 0.5f;
+
+    glUniform4f(matrix_uniform_location,
+                scale_x, (off_x + center_adjust) * scale_x - 1.0f,
+                scale_y, (off_y + center_adjust) * scale_y - 1.0f);
+
+    glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y),
+                                      0, 0, w, h);
+}
+
+/*
+ * Set up for solid rendering to the specified pixmap using alu, fg and planemask
+ * from the specified GC. Load the target color into the specified uniform
+ */
+
+void
+glamor_set_color(PixmapPtr      pixmap,
+                 CARD32         pixel,
+                 GLint          uniform)
+{
+    float       color[4];
+
+    glamor_get_rgba_from_pixel(pixel,
+                               &color[0], &color[1], &color[2], &color[3],
+                               format_for_pixmap(pixmap));
+
+    glUniform4fv(uniform, 1, color);
+}
+
+Bool
+glamor_set_solid(PixmapPtr      pixmap,
+                 GCPtr          gc,
+                 Bool           use_alu,
+                 GLint          uniform)
+{
+    CARD32      pixel;
+    int         alu = use_alu ? gc->alu : GXcopy;
+
+    if (!glamor_set_planemask(pixmap, gc->planemask))
+        return FALSE;
+
+    pixel = gc->fgPixel;
+
+    if (!glamor_set_alu(pixmap->drawable.pScreen, alu)) {
+        switch (gc->alu) {
+        case GXclear:
+            pixel = 0;
+            break;
+        case GXcopyInverted:
+            pixel = ~pixel;
+            break;
+        case GXset:
+            pixel = ~0 & gc->planemask;
+            break;
+        default:
+            return FALSE;
+        }
+    }
+    glamor_set_color(pixmap, gc->fgPixel, uniform);
+
+    return TRUE;
+}
+
+Bool
+glamor_set_texture(PixmapPtr    pixmap,
+                   PixmapPtr    texture,
+                   int          off_x,
+                   int          off_y,
+                   GLint        offset_uniform,
+                   GLint        size_uniform)
+{
+    glamor_pixmap_private *texture_priv;
+
+    texture_priv = glamor_get_pixmap_private(texture);
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv))
+        return FALSE;
+
+    if (texture_priv->type == GLAMOR_TEXTURE_LARGE)
+        return FALSE;
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, texture_priv->base.fbo->tex);
+
+    glUniform2f(offset_uniform, off_x, off_y);
+    glUniform2f(size_uniform, texture->drawable.width, texture->drawable.height);
+    return TRUE;
+}
+
+Bool
+glamor_set_tiled(PixmapPtr      pixmap,
+                 GCPtr          gc,
+                 GLint          offset_uniform,
+                 GLint          size_uniform)
+{
+    if (!glamor_set_alu(pixmap->drawable.pScreen, gc->alu))
+        return FALSE;
+
+    if (!glamor_set_planemask(pixmap, gc->planemask))
+        return FALSE;
+
+    return glamor_set_texture(pixmap,
+                              gc->tile.pixmap,
+                              -gc->patOrg.x,
+                              -gc->patOrg.y,
+                              offset_uniform,
+                              size_uniform);
+}
+
+Bool
+glamor_set_stippled(PixmapPtr      pixmap,
+                    GCPtr          gc,
+                    GLint          fg_uniform,
+                    GLint          offset_uniform,
+                    GLint          size_uniform)
+{
+    if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
+        return FALSE;
+
+    if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x, gc->patOrg.y, offset_uniform, size_uniform))
+        return FALSE;
+
+    return TRUE;
+}
diff --git a/glamor/glamor_transform.h b/glamor/glamor_transform.h
new file mode 100644
index 0000000..36b789a
--- /dev/null
+++ b/glamor/glamor_transform.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _GLAMOR_TRANSFORM_H_
+#define _GLAMOR_TRANSFORM_H_
+
+void
+glamor_set_destination_drawable(DrawablePtr     drawable,
+                                int             box_x,
+                                int             box_y,
+                                Bool            do_drawable_translate,
+                                Bool            center_offset,
+                                GLint           matrix_uniform_location,
+                                int             *p_off_x,
+                                int             *p_off_y);
+
+void
+glamor_set_color(PixmapPtr      pixmap,
+                 CARD32         pixel,
+                 GLint          uniform);
+
+Bool
+glamor_set_texture(PixmapPtr    pixmap,
+                   PixmapPtr    texture,
+                   int          off_x,
+                   int          off_y,
+                   GLint        offset_uniform,
+                   GLint        size_uniform);
+
+Bool
+glamor_set_solid(PixmapPtr      pixmap,
+                 GCPtr          gc,
+                 Bool           use_alu,
+                 GLint          uniform);
+
+Bool
+glamor_set_tiled(PixmapPtr      pixmap,
+                 GCPtr          gc,
+                 GLint          offset_uniform,
+                 GLint          size_uniform);
+
+Bool
+glamor_set_stippled(PixmapPtr      pixmap,
+                    GCPtr          gc,
+                    GLint          fg_uniform,
+                    GLint          offset_uniform,
+                    GLint          size_uniform);
+
+/*
+ * Vertex shader bits that transform X coordinates to pixmap
+ * coordinates using the matrix computed above
+ */
+
+#define GLAMOR_DECLARE_MATRIX   "uniform vec4 v_matrix;\n"
+#define GLAMOR_X_POS(x) #x " *v_matrix.x + v_matrix.y"
+#define GLAMOR_Y_POS(y) #y " *v_matrix.z + v_matrix.w"
+#if 0
+#define GLAMOR_POS(dst,src) \
+    "       " #dst ".x = " #src ".x * v_matrix.x + v_matrix.y;\n" \
+    "       " #dst ".y = " #src ".y * v_matrix.z + v_matrix.w;\n" \
+    "       " #dst ".z = 0.0;\n" \
+    "       " #dst ".w = 1.0;\n"
+#endif
+#define GLAMOR_POS(dst,src) \
+    "       " #dst ".xy = " #src ".xy * v_matrix.xz + v_matrix.yw;\n" \
+    "       " #dst ".zw = vec2(0.0,1.0);\n"
+
+#endif /* _GLAMOR_TRANSFORM_H_ */
commit 0ca7223742e9ec0594203b3a99b11441730cca1a
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 23:12:27 2014 -0700

    glamor: Add helper functions to walk pixmap tiling
    
    This adds a few helper functions to make pixmap fbo access symmetrical
    between the single fbo and tiled cases.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 22b561d..ed2c767 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -471,6 +471,52 @@ typedef struct glamor_pixmap_private {
     };
 } glamor_pixmap_private;
 
+static inline glamor_pixmap_fbo *
+glamor_pixmap_fbo_at(glamor_pixmap_private *priv, int x, int y)
+{
+    if (priv->type == GLAMOR_TEXTURE_LARGE) {
+        assert(x < priv->large.block_wcnt);
+        assert(y < priv->large.block_hcnt);
+        return priv->large.fbo_array[y * priv->large.block_wcnt + x];
+    }
+    assert (x == 0);
+    assert (y == 0);
+    return priv->base.fbo;
+}
+
+static inline BoxPtr
+glamor_pixmap_box_at(glamor_pixmap_private *priv, int x, int y)
+{
+    if (priv->type == GLAMOR_TEXTURE_LARGE) {
+        assert(x < priv->large.block_wcnt);
+        assert(y < priv->large.block_hcnt);
+        return &priv->large.box_array[y * priv->large.block_wcnt + x];
+    }
+    assert (x == 0);
+    assert (y == 0);
+    return &priv->base.box;
+}
+
+static inline int
+glamor_pixmap_wcnt(glamor_pixmap_private *priv)
+{
+    if (priv->type == GLAMOR_TEXTURE_LARGE)
+        return priv->large.block_wcnt;
+    return 1;
+}
+
+static inline int
+glamor_pixmap_hcnt(glamor_pixmap_private *priv)
+{
+    if (priv->type == GLAMOR_TEXTURE_LARGE)
+        return priv->large.block_hcnt;
+    return 1;
+}
+
+#define glamor_pixmap_loop(priv, x, y)                  \
+    for (y = 0; y < glamor_pixmap_hcnt(priv); y++)      \
+        for (x = 0; x < glamor_pixmap_wcnt(priv); x++)
+
 /* 
  * Pixmap dynamic status, used by dynamic upload feature.
  *
commit 209d004469391420130262059af43a813b2c07d7
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 23:11:40 2014 -0700

    glamor: Add bounding box to one-fbo pixmaps
    
    This lets code treat the one-fbo pixmaps more symmetrically with the
    tiled pixmaps.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 22a79e8..3094432 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -76,6 +76,10 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
         pixmap_priv->base.glamor_priv = glamor_priv;
     }
     pixmap_priv->type = type;
+    pixmap_priv->base.box.x1 = 0;
+    pixmap_priv->base.box.x2 = pixmap->drawable.width;
+    pixmap_priv->base.box.y1 = 0;
+    pixmap_priv->base.box.y2 = pixmap->drawable.height;
 }
 
 _X_EXPORT void
@@ -182,6 +186,10 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
         glamor_check_fbo_size(glamor_priv, w, h))
     {
         pixmap_priv->type = type;
+        pixmap_priv->base.box.x1 = 0;
+        pixmap_priv->base.box.y1 = 0;
+        pixmap_priv->base.box.x2 = w;
+        pixmap_priv->base.box.y2 = h;
         fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
     }
     else {
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 833450e..22b561d 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -415,6 +415,7 @@ typedef struct glamor_pixmap_private_base {
     unsigned char gl_tex:1;
     glamor_pixmap_fbo *fbo;
     PixmapPtr pixmap;
+    BoxRec box;
     int drm_stride;
     glamor_screen_private *glamor_priv;
     PicturePtr picture;
commit 82f91433e277e3711678c1b16be85e89b6c7d530
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 18 21:23:24 2014 -0700

    glamor: Get testing code using small FBOs working again
    
    Glamor has a mode where pixmaps will be constructed from numerous
    small FBOs. This allows testing of the tiled pixmap code without
    needing to create huge pixmaps.
    
    However, the render glyph code assumed that it could create a pixmap
    large enough for the glyph atlas. Instead of attempting to fix that
    (which would be disruptive and not helpful), I've added a new pixmap
    creation usage, GLAMOR_CREATE_NO_LARGE which forces allocation of a
    single large FBO.
    
    Now that we have pixmaps with varying FBO sizes, I then went around
    and fixed the few places using the global FBO max size and replaced
    that with the per-pixmap FBO tiling sizes, which were already present
    in each large pixmap.
    
    Xephyr has been changed to pass GLAMOR_CREATE_NO_LARGE when it creates
    the screen pixmap as it doesn't want to deal with tiling either.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 0d0f52c..22a79e8 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -178,7 +178,9 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
     pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
     screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
 
-    if (type == GLAMOR_MEMORY_MAP || glamor_check_fbo_size(glamor_priv, w, h)) {
+    if (type == GLAMOR_MEMORY_MAP || usage == GLAMOR_CREATE_NO_LARGE ||
+        glamor_check_fbo_size(glamor_priv, w, h))
+    {
         pixmap_priv->type = type;
         fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
     }
diff --git a/glamor/glamor.h b/glamor/glamor.h
index d05d2f4..11ec493 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -140,9 +140,16 @@ extern _X_EXPORT void glamor_set_pixmap_type(PixmapPtr pixmap,
                                              glamor_pixmap_type_t type);
 extern _X_EXPORT void glamor_destroy_textured_pixmap(PixmapPtr pixmap);
 extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
+
 extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
                                                 int depth, unsigned int usage);
 
+#define GLAMOR_CREATE_PIXMAP_CPU        0x100
+#define GLAMOR_CREATE_PIXMAP_FIXUP      0x101
+#define GLAMOR_CREATE_FBO_NO_FBO        0x103
+#define GLAMOR_CREATE_PIXMAP_MAP        0x104
+#define GLAMOR_CREATE_NO_LARGE          0x105
+
 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo).
  *
  * @front: front pixmap.
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index 640b6fd..4f6da67 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -361,9 +361,6 @@ glamor_create_fbo(glamor_screen_private *glamor_priv,
     GLint tex = 0;
     int cache_flag;
 
-    if (!glamor_check_fbo_size(glamor_priv, w, h))
-        return NULL;
-
     if (flag == GLAMOR_CREATE_FBO_NO_FBO)
         goto new_fbo;
 
diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index 2b2c735..a04ae82 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -332,7 +332,7 @@ glamor_realize_glyph_caches(ScreenPtr pScreen)
         pixmap = pScreen->CreatePixmap(pScreen,
                                        CACHE_PICTURE_SIZE,
                                        CACHE_PICTURE_SIZE + MASK_CACHE_MAX_SIZE,
-                                       depth, 0);
+                                       depth, GLAMOR_CREATE_NO_LARGE);
         if (!pixmap)
             goto bail;
 
diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c
index b8c0640..b3a8d5d 100644
--- a/glamor/glamor_largepixmap.c
+++ b/glamor/glamor_largepixmap.c
@@ -1015,7 +1015,6 @@ glamor_composite_largepixmap_region(CARD8 op,
                                     INT16 x_dest, INT16 y_dest,
                                     CARD16 width, CARD16 height)
 {
-    glamor_screen_private *glamor_priv;
     glamor_pixmap_clipped_regions *clipped_dest_regions;
     glamor_pixmap_clipped_regions *clipped_source_regions;
     glamor_pixmap_clipped_regions *clipped_mask_regions;
@@ -1044,9 +1043,8 @@ glamor_composite_largepixmap_region(CARD8 op,
     else
         mask_repeat_type = RepeatNone;
 
-    glamor_priv = dest_pixmap_priv->base.glamor_priv;
-    fixed_block_width = glamor_priv->max_fbo_size;
-    fixed_block_height = glamor_priv->max_fbo_size;
+    fixed_block_width = dest_pixmap_priv->large.block_w;
+    fixed_block_height = dest_pixmap_priv->large.block_h;
     /* If we got an totally out-of-box region for a source or mask
      * region without repeat, we need to set it as null_source and
      * give it a solid color (0,0,0,0). */
@@ -1112,8 +1110,8 @@ glamor_composite_largepixmap_region(CARD8 op,
 
     /*compute the correct block width and height whose transformed source/mask
      *region can fit into one texture.*/
-    if (force_clip || fixed_block_width < glamor_priv->max_fbo_size
-        || fixed_block_height < glamor_priv->max_fbo_size)
+    if (force_clip || fixed_block_width < dest_pixmap_priv->large.block_w
+        || fixed_block_height < dest_pixmap_priv->large.block_h)
         clipped_dest_regions =
             glamor_compute_clipped_regions_ext(dest_pixmap_priv, region,
                                                &n_dest_regions,
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 615faad..891ecdd 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -1013,10 +1013,9 @@ glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
             clipped_regions =
                 glamor_compute_clipped_regions_ext(pixmap_priv, &region,
                                                    &n_region,
-                                                   pixmap_priv->base.
-                                                   glamor_priv->max_fbo_size,
-                                                   pixmap_priv->base.
-                                                   glamor_priv->max_fbo_size, 0,
+                                                   pixmap_priv->large.block_w,
+                                                   pixmap_priv->large.block_h,
+                                                   0,
                                                    0);
         DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap);
         for (i = 0; i < n_region; i++) {
@@ -1374,10 +1373,9 @@ glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
             clipped_regions =
                 glamor_compute_clipped_regions_ext(pixmap_priv, &region,
                                                    &n_region,
-                                                   pixmap_priv->base.
-                                                   glamor_priv->max_fbo_size,
-                                                   pixmap_priv->base.
-                                                   glamor_priv->max_fbo_size, 0,
+                                                   pixmap_priv->large.block_w,
+                                                   pixmap_priv->large.block_h,
+                                                   0,
                                                    0);
 
         DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index d4d2e75..833450e 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -153,13 +153,6 @@ enum glamor_gl_flavor {
     GLAMOR_GL_ES2               // OPENGL ES2.0 API
 };
 
-#define GLAMOR_CREATE_PIXMAP_CPU  0x100
-#define GLAMOR_CREATE_PIXMAP_FIXUP 0x101
-#define GLAMOR_CREATE_FBO_NO_FBO   0x103
-#define GLAMOR_CREATE_PIXMAP_MAP 0x104
-
-#define GLAMOR_CREATE_TEXTURE_EXACT_SIZE 0x104
-
 #define GLAMOR_NUM_GLYPH_CACHE_FORMATS 2
 
 #define GLAMOR_COMPOSITE_VBO_VERT_CNT (64*1024)
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 3260d95..3054f5f 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -1260,7 +1260,9 @@ ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
     screen_pixmap = pScreen->CreatePixmap(pScreen,
                                           pScreen->width,
                                           pScreen->height,
-                                          pScreen->rootDepth, 0);
+                                          pScreen->rootDepth,
+                                          GLAMOR_CREATE_NO_LARGE);
+
     pScreen->SetScreenPixmap(screen_pixmap);
 
     /* Tell the GLX code what to GL texture to read from. */
commit 11e2f0de71fa341f8b0b1da0a1b9ccbfa6550a50
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 18 21:35:41 2014 -0700

    mi: miPutImage with XYPixmap failed at depth 32 on 64-bit machines
    
    The X server still has 'unsigned long' in a few places to hold 32 bit
    values. One of those is in miPutImage where it's holding the temporary
    planemask for XYPixmap format images.
    
    It computed the highest plane in the source image with 1 << (depth -
    1). On 64-bit machines, taking that value and storing it in an
    unsigned long promotes it to a signed 64-bit value
    (0xffffffff80000000).
    
    Then, it loops over that value, shifting one bit right each time,
    waiting for it to go to zero.. That takes 64 iterations, and ends up
    with some mystic planemask values *and* walking off the end of the
    source image data and out into space.
    
    A simple cast is all that is required to compute the correct initial
    plane mask (0x0000000080000000), at which point the loop operates
    correctly once again.
    
    Checking the fbPutImage code, I note that this same bug was fixed
    in 2006 by Aaron Plattner in commit
    f39fd4242902eaa862321d39337f429dd14ebacf
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/mi/mibitblt.c b/mi/mibitblt.c
index b0d14ae..3ed4ed1 100644
--- a/mi/mibitblt.c
+++ b/mi/mibitblt.c
@@ -730,7 +730,7 @@ miPutImage(DrawablePtr pDraw, GCPtr pGC, int depth,
         ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcv);
         bytesPer = (long) h *BitmapBytePad(w + leftPad);
 
-        for (i = 1 << (depth - 1); i != 0; i >>= 1, pImage += bytesPer) {
+        for (i = (unsigned long) 1 << (depth - 1); i != 0; i >>= 1, pImage += bytesPer) {
             if (i & oldPlanemask) {
                 gcv[0].val = (XID) i;
                 ChangeGC(NullClient, pGC, GCPlaneMask, gcv);
commit ae87b536155207e6e28b68963593a7ab09792e08
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 15 23:53:53 2014 -0700

    dix: Allow NULL stipple in ChangeGC
    
    miOpqStipDrawable resets the stipple after painting. When that stipple
    was NULL, ChangeGC needs to handle that and not crash.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/dix/gc.c b/dix/gc.c
index efe6d60..88d6501 100644
--- a/dix/gc.c
+++ b/dix/gc.c
@@ -261,12 +261,14 @@ ChangeGC(ClientPtr client, GC * pGC, BITS32 mask, ChangeGCValPtr pUnion)
         case GCStipple:
             NEXT_PTR(PixmapPtr, pPixmap);
 
-            if ((pPixmap->drawable.depth != 1) ||
-                (pPixmap->drawable.pScreen != pGC->pScreen)) {
+            if (pPixmap && ((pPixmap->drawable.depth != 1) ||
+                            (pPixmap->drawable.pScreen != pGC->pScreen)))
+            {
                 error = BadMatch;
             }
             else {
-                pPixmap->refcnt++;
+                if (pPixmap)
+                    pPixmap->refcnt++;
                 if (pGC->stipple)
                     (*pGC->pScreen->DestroyPixmap) (pGC->stipple);
                 pGC->stipple = pPixmap;
commit 2e040f41de18f4d46e649561b6efb043195fdfbe
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:55 2014 +0100

    glamor: Drop feature dependent optimization on startup.
    
    We don't care that much about startup time to write different code paths...
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 62236b9..cdf8eff 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -412,27 +412,10 @@ glamor_init_composite_shaders(ScreenPtr screen)
 
     eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2;
 
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, NULL, GL_STATIC_DRAW);
-        eb = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
-    }
-    else {
-        eb = malloc(eb_size);
-    }
-
-    if (eb == NULL)
-        FatalError
-            ("fatal error, fail to get element buffer. GL context may be not created correctly.\n");
+    eb = XNFalloc(eb_size);
     glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT);
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-    }
-    else {
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
-
-        free(eb);
-    }
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
+    free(eb);
 
     glamor_put_context(glamor_priv);
 }
commit 2e75d974bcfdd879d7417cc02892b78eaea5e888
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:54 2014 +0100

    glamor: Remove unneeded unbindings.
    
    They are already cleared in glamor_put_vbo_space.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index ce24d73..c24f342 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -1120,8 +1120,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
         free(stop_colors);
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
@@ -1140,8 +1138,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
             free(stop_colors);
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glamor_put_context(glamor_priv);
@@ -1469,8 +1465,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
         free(stop_colors);
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
@@ -1489,8 +1483,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
             free(stop_colors);
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glamor_put_context(glamor_priv);
commit 7c4e1472966d9d3d6432621c3114f491a5378604
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:53 2014 +0100

    glamor: Always keep GL_ELEMENT_ARRAY_BUFFER bound to the same IB.
    
    We never used glDrawElements() with a different index buffer.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index 7461b62..2fa726e 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -218,9 +218,6 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
         }
     }
 
-    if (_X_UNLIKELY(nbox > 1))
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
-
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, 2 * sizeof(float), vertices);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 38dac68..ce24d73 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -1121,7 +1121,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     }
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -1142,7 +1141,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     }
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -1472,7 +1470,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     }
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -1493,7 +1490,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     }
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index c0ee22c..62236b9 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -427,11 +427,9 @@ glamor_init_composite_shaders(ScreenPtr screen)
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     }
     else {
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
         free(eb);
     }
@@ -448,6 +446,7 @@ glamor_fini_composite_shaders(ScreenPtr screen)
 
     glamor_priv = glamor_get_screen_private(screen);
     glamor_get_context(glamor_priv);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDeleteBuffers(1, &glamor_priv->ebo);
 
     for (i = 0; i < SHADER_SOURCE_COUNT; i++)
@@ -706,8 +705,6 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
     glamor_get_context(glamor_priv);
     vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
-
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
                           glamor_priv->vb_stride, vbo_offset);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
@@ -1329,7 +1326,6 @@ glamor_composite_with_shader(CARD8 op,
         }
     }
 
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 969ab68..c76b8bb 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -637,8 +637,6 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
 
     vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
-
     /* Set the vertex pointer. */
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, glamor_priv->vb_stride,
@@ -977,7 +975,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     ret = TRUE;
 
  TRAPEZOID_RESET_GL:
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
@@ -1415,8 +1412,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
 
     pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale));
 
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-
     /* Now draw the Trapezoid mask. */
     glUseProgram(trapezoid_prog);
 
@@ -1562,7 +1557,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
         }
     }
 
-    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glBlendFunc(GL_ONE, GL_ZERO);
     glDisable(GL_BLEND);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
commit 82168b1e6ede48898be8a64b1c93b7d82ef65702
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:52 2014 +0100

    glamor: Select VBO path by ARB_mbr extension.
    
    The mbr path was hard coded enabled for desktop gl and disabled for
    gles.  But there are both desktop without mbr and GLES with mbr.
    
    v2: Don't forget to update the fini path, too (change by anholt)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index eb13430..0d0f52c 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -378,6 +378,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         epoxy_has_gl_extension("GL_MESA_pack_invert");
     glamor_priv->has_fbo_blit =
         epoxy_has_gl_extension("GL_EXT_framebuffer_blit");
+    glamor_priv->has_map_buffer_range =
+        epoxy_has_gl_extension("GL_ARB_map_buffer_range");
     glamor_priv->has_buffer_storage =
         epoxy_has_gl_extension("GL_ARB_buffer_storage");
     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 0f0b0f3..d4d2e75 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -213,6 +213,7 @@ typedef struct glamor_screen_private {
     enum glamor_gl_flavor gl_flavor;
     int has_pack_invert;
     int has_fbo_blit;
+    int has_map_buffer_range;
     int has_buffer_storage;
     int has_khr_debug;
     int max_fbo_size;
diff --git a/glamor/glamor_vbo.c b/glamor/glamor_vbo.c
index 5e98bfe..2731692 100644
--- a/glamor/glamor_vbo.c
+++ b/glamor/glamor_vbo.c
@@ -96,7 +96,7 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
         *vbo_offset = (void *)(uintptr_t)glamor_priv->vbo_offset;
         data = glamor_priv->vb + glamor_priv->vbo_offset;
         glamor_priv->vbo_offset += size;
-    } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+    } else if (glamor_priv->has_map_buffer_range) {
         if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
             glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
             glamor_priv->vbo_offset = 0;
@@ -147,7 +147,7 @@ glamor_put_vbo_space(ScreenPtr screen)
          * persistent mapping, so we can leave it around until we
          * reach the end of the buffer.
          */
-    } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+    } else if (glamor_priv->has_map_buffer_range) {
         glUnmapBuffer(GL_ARRAY_BUFFER);
     } else {
         glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
@@ -179,7 +179,7 @@ glamor_fini_vbo(ScreenPtr screen)
     glamor_get_context(glamor_priv);
 
     glDeleteBuffers(1, &glamor_priv->vbo);
-    if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP)
+    if (!glamor_priv->has_map_buffer_range)
         free(glamor_priv->vb);
 
     glamor_put_context(glamor_priv);
commit 53df6e8c3bd7025883b9614a549fbf268c110b74
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:51 2014 +0100

    glamor: Update GL requirements to 2.1.
    
    We will never ever run on OpenGL 1.2 as we use shaders everywhere.
    2.0 may be enough, but we also often use PBOs and our big shaders
    won't fit into the first GLSL limits.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index ef969e2..eb13430 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -357,8 +357,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
      * Windows with Intel 4-series (G45) graphics or older.
      */
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        if (gl_version < 13) {
-            ErrorF("Require OpenGL version 1.3 or later.\n");
+        if (gl_version < 21) {
+            ErrorF("Require OpenGL version 2.1 or later.\n");
             goto fail;
         }
     } else {
commit 15d36444acc7a2890ade8e320dc16d627a9d2035
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:50 2014 +0100

    glamor: Use epoxy_gl_version() instead of rolling our own.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 9d171b7..ef969e2 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -341,7 +341,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     else
         glamor_priv->gl_flavor = GLAMOR_GL_ES2;
 
-    gl_version = glamor_gl_get_version();
+    gl_version = epoxy_gl_version();
 
     /* We'd like to require GL_ARB_map_buffer_range or
      * GL_OES_map_buffer_range, since it offers more information to
@@ -357,12 +357,12 @@ glamor_init(ScreenPtr screen, unsigned int flags)
      * Windows with Intel 4-series (G45) graphics or older.
      */
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) {
+        if (gl_version < 13) {
             ErrorF("Require OpenGL version 1.3 or later.\n");
             goto fail;
         }
     } else {
-        if (gl_version < GLAMOR_GL_VERSION_ENCODE(2, 0)) {
+        if (gl_version < 20) {
             ErrorF("Require Open GLES2.0 or later.\n");
             goto fail;
         }
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index eeaa595..5711be7 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -559,26 +559,3 @@ glamor_bitmap_to_region(PixmapPtr pixmap)
     return ret;
 }
 
-int
-glamor_gl_get_version(void)
-{
-    int major, minor;
-    const char *version = (const char *) glGetString(GL_VERSION);
-    const char *dot = version == NULL ? NULL : strchr(version, '.');
-    const char *major_start = dot;
-
-    /* Sanity check */
-    if (dot == NULL || dot == version || *(dot + 1) == '\0') {
-        major = 0;
-        minor = 0;
-    }
-    else {
-        /* Find the start of the major version in the string */
-        while (major_start > version && *major_start != ' ')
-            --major_start;
-        major = strtol(major_start, NULL, 10);
-        minor = strtol(dot + 1, NULL, 10);
-    }
-
-    return GLAMOR_GL_VERSION_ENCODE(major, minor);
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index f278bef..0f0b0f3 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -619,11 +619,6 @@ Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
 Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask);
 RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
-int glamor_gl_get_version(void);
-
-#define GLAMOR_GL_VERSION_ENCODE(major, minor) ( \
-          ((major) * 256)                       \
-        + ((minor) *   1))
 
 /* glamor_fill.c */
 Bool glamor_fill(DrawablePtr drawable,
commit 9d87f66e862a521553d48aa73e5ee97431d36ad3
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:49 2014 +0100

    glamor: Use epoxy_has_gl_extension() instead of rolling our own.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 0f7d68b..9d171b7 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -367,19 +367,19 @@ glamor_init(ScreenPtr screen, unsigned int flags)
             goto fail;
         }
 
-        if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) {
+        if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
             ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
             goto fail;
         }
     }
 
-    glamor_priv->has_khr_debug = glamor_gl_has_extension("GL_KHR_debug");
+    glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug");
     glamor_priv->has_pack_invert =
-        glamor_gl_has_extension("GL_MESA_pack_invert");
+        epoxy_has_gl_extension("GL_MESA_pack_invert");
     glamor_priv->has_fbo_blit =
-        glamor_gl_has_extension("GL_EXT_framebuffer_blit");
+        epoxy_has_gl_extension("GL_EXT_framebuffer_blit");
     glamor_priv->has_buffer_storage =
-        glamor_gl_has_extension("GL_ARB_buffer_storage");
+        epoxy_has_gl_extension("GL_ARB_buffer_storage");
     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
 #ifdef MAX_FBO_SIZE
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 6c0b3c8..eeaa595 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -559,28 +559,6 @@ glamor_bitmap_to_region(PixmapPtr pixmap)
     return ret;
 }
 
-/* Borrow from cairo. */
-Bool
-glamor_gl_has_extension(const char *extension)
-{
-    const char *pext;
-    int ext_len;
-
-    ext_len = strlen(extension);
-
-    pext = (const char *) glGetString(GL_EXTENSIONS);
-
-    if (pext == NULL || extension == NULL)
-        return FALSE;
-
-    while ((pext = strstr(pext, extension)) != NULL) {
-        if (pext[ext_len] == ' ' || pext[ext_len] == '\0')
-            return TRUE;
-        pext += ext_len;
-    }
-    return FALSE;
-}
-
 int
 glamor_gl_get_version(void)
 {
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index bc7d3f8..f278bef 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -619,7 +619,6 @@ Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
 Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask);
 RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
-Bool glamor_gl_has_extension(const char *extension);
 int glamor_gl_get_version(void);
 
 #define GLAMOR_GL_VERSION_ENCODE(major, minor) ( \
commit 708fe0625f31ad39ba54f27f04d17ed2aa621cad
Author: Markus Wick <markus at selfnet.de>
Date:   Tue Mar 18 09:42:48 2014 +0100

    glamor: Use glsl "fract/mod" instead of "while" in gradient shaders.
    
    This fixes gtkperf. It seemed to hang forever.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index f77d6a8..38dac68 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -247,7 +247,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
 	    "{\n"\
 	    "    float t = 0.0;\n"\
 	    "    float sqrt_value;\n"\
-	    "    int revserse = 0;\n"\
 	    "    t_invalid = 0;\n"\
 	    "    \n"\
 	    "    vec3 tmp = vec3(source_texture.x, source_texture.y, 1.0);\n"\
@@ -295,30 +294,11 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
 	    "    }\n"\
 	    "    \n"\
 	    "    if(repeat_type == %d){\n" /* repeat normal*/\
-	    "        while(t > 1.0) \n"\
-	    "            t = t - 1.0; \n"\
-	    "        while(t < 0.0) \n"\
-	    "            t = t + 1.0; \n"\
+	    "        t = fract(t);\n"\
 	    "    }\n"\
 	    "    \n"\
 	    "    if(repeat_type == %d) {\n" /* repeat reflect*/\
-	    "        while(t > 1.0) {\n"\
-	    "            t = t - 1.0; \n"\
-	    "            if(revserse == 0)\n"\
-	    "                revserse = 1;\n"\
-	    "            else\n"\
-	    "                revserse = 0;\n"\
-	    "        }\n"\
-	    "        while(t < 0.0) {\n"\
-	    "            t = t + 1.0; \n"\
-	    "            if(revserse == 0)\n"\
-	    "                revserse = 1;\n"\
-	    "            else\n"\
-	    "                revserse = 0;\n"\
-	    "        }\n"\
-	    "        if(revserse == 1) {\n"\
-	    "            t = 1.0 - t; \n"\
-	    "        }\n"\
+	    "        t = abs(fract(t * 0.5 + 0.5) * 2.0 - 1.0);\n"\
 	    "    }\n"\
 	    "    \n"\
 	    "    return t;\n"\
@@ -492,7 +472,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
 	    "    vec4 stop_color_before;\n"\
 	    "    vec4 stop_color_after;\n"\
 	    "    float new_alpha; \n"\
-	    "    int revserse = 0;\n"\
 	    "    vec4 gradient_color;\n"\
 	    "    float percentage; \n"\
 	    "    vec3 source_texture_trans = transform_mat * tmp;\n"\
@@ -512,30 +491,11 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
 	    "    distance = distance - _p1_distance; \n"\
 	    "    \n"\
 	    "    if(repeat_type == %d){\n" /* repeat normal*/\
-	    "        while(distance > _pt_distance) \n"\
-	    "            distance = distance - (_pt_distance); \n"\
-	    "        while(distance < 0.0) \n"\
-	    "            distance = distance + (_pt_distance); \n"\
+	    "        distance = mod(distance, _pt_distance);\n"\
 	    "    }\n"\
 	    "    \n"\
 	    "    if(repeat_type == %d) {\n" /* repeat reflect*/\
-	    "        while(distance > _pt_distance) {\n"\
-	    "            distance = distance - (_pt_distance); \n"\
-	    "            if(revserse == 0)\n"\
-	    "                revserse = 1;\n"\
-	    "            else\n"\
-	    "                revserse = 0;\n"\
-	    "        }\n"\
-	    "        while(distance < 0.0) {\n"\
-	    "            distance = distance + (_pt_distance); \n"\
-	    "            if(revserse == 0)\n"\
-	    "                revserse = 1;\n"\
-	    "            else\n"\
-	    "                revserse = 0;\n"\
-	    "        }\n"\
-	    "        if(revserse == 1) {\n"\
-	    "            distance = (_pt_distance) - distance; \n"\
-	    "        }\n"\
+	    "        distance = abs(mod(distance + _pt_distance, 2.0 * _pt_distance) - _pt_distance);\n"\
 	    "    }\n"\
 	    "    \n"\
 	    "    len_percentage = distance/(_pt_distance);\n"\
commit 84ff8960722fa9baf6ad70756b9c335bf2a5e515
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Mar 18 09:42:47 2014 +0100

    kdrive: Remove duplicated definitions of some XV-related structs.
    
    v2: Fix crash because of removed strdup. (by Markus Wick)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net> (v2)

diff --git a/hw/kdrive/src/kxv.c b/hw/kdrive/src/kxv.c
index 445eb60..9cc0edd 100644
--- a/hw/kdrive/src/kxv.c
+++ b/hw/kdrive/src/kxv.c
@@ -385,28 +385,7 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
 
             for (i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
                  i < adaptorPtr->nImages; i++, pi++, imagePtr++) {
-                pi->id = imagePtr->id;
-                pi->type = imagePtr->type;
-                pi->byte_order = imagePtr->byte_order;
-                memcpy(pi->guid, imagePtr->guid, 16);
-                pi->bits_per_pixel = imagePtr->bits_per_pixel;
-                pi->format = imagePtr->format;
-                pi->num_planes = imagePtr->num_planes;
-                pi->depth = imagePtr->depth;
-                pi->red_mask = imagePtr->red_mask;
-                pi->green_mask = imagePtr->green_mask;
-                pi->blue_mask = imagePtr->blue_mask;
-                pi->y_sample_bits = imagePtr->y_sample_bits;
-                pi->u_sample_bits = imagePtr->u_sample_bits;
-                pi->v_sample_bits = imagePtr->v_sample_bits;
-                pi->horz_y_period = imagePtr->horz_y_period;
-                pi->horz_u_period = imagePtr->horz_u_period;
-                pi->horz_v_period = imagePtr->horz_v_period;
-                pi->vert_y_period = imagePtr->vert_y_period;
-                pi->vert_u_period = imagePtr->vert_u_period;
-                pi->vert_v_period = imagePtr->vert_v_period;
-                memcpy(pi->component_order, imagePtr->component_order, 32);
-                pi->scanline_order = imagePtr->scanline_order;
+                memcpy(pi, imagePtr, sizeof(*pi));
             }
             pa->nImages = adaptorPtr->nImages;
             pa->pImages = pImage;
@@ -417,9 +396,7 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
              calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) {
             for (pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i =
                  0; i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) {
-                pat->flags = attributePtr->flags;
-                pat->min_value = attributePtr->min_value;
-                pat->max_value = attributePtr->max_value;
+                memcpy(pat, attributePtr, sizeof(*pat));
                 pat->name = strdup(attributePtr->name);
             }
             pa->nAttributes = adaptorPtr->nAttributes;
diff --git a/hw/kdrive/src/kxv.h b/hw/kdrive/src/kxv.h
index 4f644c2..85a030e 100644
--- a/hw/kdrive/src/kxv.h
+++ b/hw/kdrive/src/kxv.h
@@ -56,34 +56,7 @@ of the copyright holder.
 #define VIDEO_OVERLAID_STILLS			0x00000008
 #define VIDEO_CLIP_TO_VIEWPORT			0x00000010
 
-typedef struct {
-    int id;
-    int type;
-    int byte_order;
-    unsigned char guid[16];
-    int bits_per_pixel;
-    int format;
-    int num_planes;
-
-    /* for RGB formats only */
-    int depth;
-    unsigned int red_mask;
-    unsigned int green_mask;
-    unsigned int blue_mask;
-
-    /* for YUV formats only */
-    unsigned int y_sample_bits;
-    unsigned int u_sample_bits;
-    unsigned int v_sample_bits;
-    unsigned int horz_y_period;
-    unsigned int horz_u_period;
-    unsigned int horz_v_period;
-    unsigned int vert_y_period;
-    unsigned int vert_u_period;
-    unsigned int vert_v_period;
-    char component_order[32];
-    int scanline_order;
-} KdImageRec, *KdImagePtr;
+typedef XvImageRec KdImageRec, *KdImagePtr;
 
 typedef struct {
     KdScreenInfo *screen;
@@ -158,12 +131,7 @@ typedef struct {
     short class;
 } KdVideoFormatRec, *KdVideoFormatPtr;
 
-typedef struct {
-    int flags;
-    int min_value;
-    int max_value;
-    char *name;
-} KdAttributeRec, *KdAttributePtr;
+typedef XvAttributeRec KdAttributeRec, *KdAttributePtr;
 
 typedef struct {
     unsigned int type;
commit 370c8c75ca6aebb5d93d2ab87c9c8ffac21fc57d
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Wed Mar 19 11:28:57 2014 -0400

    xfree86: glamor_egl subdir must be distributed - breaks distcheck
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index a315bbc..18fa99b 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -43,7 +43,7 @@ SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
 DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
                parser ramdac shadowfb vbe vgahw \
                loader dixmods dri dri2 exa modes \
-	       utils doc man
+	       utils doc man glamor_egl
 
 bin_PROGRAMS = Xorg
 nodist_Xorg_SOURCES = sdksyms.c
commit 870bbf85e63a59f252f3ea9d63e28f083359d990
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Wed Mar 19 14:17:15 2014 -0400

    ephyr: typo where "()" should be "$()" in the Makefile - breaks make dist
    
    make[3]: Entering directory `/home/nadon/xorg/src/xserver/hw/kdrive/ephyr'
    make[3]: *** No rule to make target `()', needed by `distdir'.  Stop.
    make[3]: Leaving directory `/home/nadon/xorg/src/xserver/hw/kdrive/ephyr'
    make[2]: *** [distdir] Error 1
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am
index 040993c..00a53d0 100644
--- a/hw/kdrive/ephyr/Makefile.am
+++ b/hw/kdrive/ephyr/Makefile.am
@@ -38,7 +38,7 @@ if GLAMOR
 GLAMOR_SRCS = \
 	ephyr_glamor_glx.c \
 	ephyr_glamor_glx.h \
-	()
+	$()
 endif
 
 if DRI
commit dc48bd653c7e1013e2d69e3f59ae3cbc0c893473
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Mar 24 16:32:01 2014 +0100

    systemd-logind: Monitor systemd-logind going away
    
    When we're using server managed-fds through systemd-logind, systemd-logind
    *must* keep running while we are using it, as it does things like drmSetMaster
    and drmDropMaster for us on vt-switch.
    
    On a systemd-logind restart, we cannot simply re-connect since we will then
    get a different fd for the /dev/dri/card# node, and we've tied a lot of
    state to the old fd. I've discussed this with the systemd people, and in the
    future there may be a restart mechanism were systemd-logind passed fds from
    the old logind to the new logind. But for now there answer is simply:
    "Don't restart systemd-logind", and there never really is a good reason to
    restart it.
    
    So to ensure unpleasentness if people do decide to restart systemd-logind
    anyways (or when it crashes), monitor logind going away and make this a fatal
    error. This avoids getting a hard-hung machine on the next vt-switch and will
    hopefully quickly educate users to not restart systemd-logind while they have
    an X session using it active.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index 62858b0..ed670a8 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -310,10 +310,31 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data)
     dbus_int32_t major, minor;
     char *pause_str;
 
-    if (strcmp(dbus_message_get_path(message), info->session) != 0)
+    dbus_error_init(&error);
+
+    if (dbus_message_is_signal(message,
+                               "org.freedesktop.DBus", "NameOwnerChanged")) {
+        char *name, *old_owner, *new_owner;
+
+        dbus_message_get_args(message, &error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_STRING, &old_owner,
+                              DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID);
+        if (dbus_error_is_set(&error)) {
+            LogMessage(X_ERROR, "systemd-logind: NameOwnerChanged: %s\n",
+                       error.message);
+            dbus_error_free(&error);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+
+        if (name && strcmp(name, "org.freedesktop.login1") == 0)
+            FatalError("systemd-logind disappeared (stopped/restarted?)\n");
+
         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
 
-    dbus_error_init(&error);
+    if (strcmp(dbus_message_get_path(message), info->session) != 0)
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
     if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
                                "PauseDevice")) {
@@ -472,6 +493,15 @@ connect_hook(DBusConnection *connection, void *data)
         goto cleanup;
     }
 
+    dbus_bus_add_match(connection,
+        "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus'",
+        &error);
+    if (dbus_error_is_set(&error)) {
+        LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
     /*
      * HdG: This is not useful with systemd <= 208 since the signal only
      * contains invalidated property names there, rather than property, val
commit c0d3a13e7ee42be26d6d1923c9f3ae0355497869
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Mar 24 16:31:59 2014 +0100

    Buildsys: Create SUID_WRAPPER_DIR before using it
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 418a35a..8f13905 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -105,6 +105,7 @@ if INSTALL_SETUID
 	chmod u+s $(DESTDIR)$(bindir)/Xorg
 endif
 if SUID_WRAPPER
+	$(MKDIR_P) $(DESTDIR)$(SUID_WRAPPER_DIR)
 	mv $(DESTDIR)$(bindir)/Xorg $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.bin
 	${INSTALL} -m 755 Xorg.sh $(DESTDIR)$(bindir)/Xorg
 	-chown root $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.wrap && chmod u+s $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.wrap
commit 6289f71494453d34614b7ff1238840681c2472af
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Tue Mar 25 14:00:13 2014 -0400

    suid: adding Xorg.sh.in to EXTRA_DIST is redundant
    
    All files specified in AC_CONFIG_FILES get distributed automatically.
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index a315bbc..418a35a 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -89,7 +89,7 @@ endif
 
 BUILT_SOURCES = xorg.conf.example
 DISTCLEANFILES = xorg.conf.example
-EXTRA_DIST = xorgconf.cpp Xorg.sh.in
+EXTRA_DIST = xorgconf.cpp
 
 # Without logdir, X will post an error on the terminal and will not start
 install-data-local:
commit b82ef51509bf24e8eafeb615a3e2f4fcd559554e
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Tue Mar 25 13:49:02 2014 -0400

    suid: add generated Xorg.sh to hw/xfree86/.gitignore
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/.gitignore b/hw/xfree86/.gitignore
index 997a94e..fb6830b 100644
--- a/hw/xfree86/.gitignore
+++ b/hw/xfree86/.gitignore
@@ -1,4 +1,5 @@
 Xorg
+Xorg.sh
 xorg.conf.example
 sdksyms.c
 sdksyms.dep
commit ca8f26f63694c27fa488a3b58ea6f00b7dd50f81
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Tue Mar 25 13:48:52 2014 -0400

    suid: replace deprecated AC_HELP_STRING with AS_HELP_STRING
    
    Fixes automake warning.
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index a75ba8f..f051414 100644
--- a/configure.ac
+++ b/configure.ac
@@ -624,8 +624,8 @@ AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg
 AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
 AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
 AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
-AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
-AC_ARG_ENABLE(suid-wrapper, AC_HELP_STRING([--enable-suid-wrapper], [Build suid-root wrapper for legacy driver support on rootless xserver systems (default: no)]), [SUID_WRAPPER=$enableval], [SUID_WRAPPER=no])
+AC_ARG_ENABLE(systemd-logind, AS_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
+AC_ARG_ENABLE(suid-wrapper, AS_HELP_STRING([--enable-suid-wrapper], [Build suid-root wrapper for legacy driver support on rootless xserver systems (default: no)]), [SUID_WRAPPER=$enableval], [SUID_WRAPPER=no])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
commit bda6fdc71c25b0c3f3747f445103a1995a5713f4
Merge: e46820f 78167a9
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 25 16:06:03 2014 -0700

    Merge remote-tracking branch 'whot/for-keith'

commit e46820fb897600800b5f3297a59039556774e9c5
Author: Emil Velikov <emil.l.velikov at gmail.com>
Date:   Thu Sep 26 20:28:37 2013 +0100

    miinitext: introduce LoadExtensionList() to replace over LoadExtension()
    
    Looping around LoadExtension() meant that ExtensionModuleList was reallocated
    on every extension. Using LoadExtensionList() we pass an array thus the
    function can do the reallocation in one go, and then loop and setup the
    ExtensionModuleList.
    
    Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    
    v2: Update ephyr [Keith Packard]
    v3: Eliminate const warnings in LoadExtensionList [Keith Packard]
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
index 7adcba0..fd2ade0 100644
--- a/hw/dmx/dmxinit.c
+++ b/hw/dmx/dmxinit.c
@@ -597,10 +597,8 @@ static void dmxAddExtensions(Bool glxSupported)
         { GlxExtensionInit, "GLX", &glxSupported },
 #endif
     };
-    int i;
 
-    for (i = 0; i < ARRAY_SIZE(dmxExtensions); i++)
-        LoadExtension(&dmxExtensions[i], TRUE);
+    LoadExtensionList(dmxExtensions, ARRAY_SIZE(dmxExtensions), TRUE);
 }
 
 /** This routine is called in Xserver/dix/main.c from \a main(). */
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index 807e717..fac84cd 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -65,10 +65,7 @@ static const ExtensionModule ephyrExtensions[] = {
 static
 void ephyrExtensionInit(void)
 {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ephyrExtensions); i++)
- LoadExtension(&ephyrExtensions[i], TRUE);
+    LoadExtensionList(ephyrExtensions, ARRAY_SIZE(ephyrExtensions), TRUE);
 }
 
 
diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c
index 2175ac6..9c49264 100644
--- a/hw/vfb/InitOutput.c
+++ b/hw/vfb/InitOutput.c
@@ -892,10 +892,7 @@ static const ExtensionModule vfbExtensions[] = {
 static
 void vfbExtensionInit(void)
 {
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(vfbExtensions); i++)
-        LoadExtension(&vfbExtensions[i], TRUE);
+    LoadExtensionList(vfbExtensions, ARRAY_SIZE(vfbExtensions), TRUE);
 }
 
 void
diff --git a/hw/xfree86/common/xf86Extensions.c b/hw/xfree86/common/xf86Extensions.c
index c80de34..25b2bc3 100644
--- a/hw/xfree86/common/xf86Extensions.c
+++ b/hw/xfree86/common/xf86Extensions.c
@@ -132,10 +132,7 @@ load_extension_config(void)
 void
 xf86ExtensionInit(void)
 {
-    int i;
-
     load_extension_config();
 
-    for (i = 0; i < ARRAY_SIZE(extensionModules); i++)
-	LoadExtension(&extensionModules[i], TRUE);
+    LoadExtensionList(extensionModules, ARRAY_SIZE(extensionModules), TRUE);
 }
diff --git a/hw/xfree86/dixmods/glxmodule.c b/hw/xfree86/dixmods/glxmodule.c
index bf7d182..d53c665 100644
--- a/hw/xfree86/dixmods/glxmodule.c
+++ b/hw/xfree86/dixmods/glxmodule.c
@@ -47,10 +47,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 static MODULESETUPPROTO(glxSetup);
 
-static const ExtensionModule GLXExt = {
-    GlxExtensionInit,
-    "GLX",
-    &noGlxExtension
+static const ExtensionModule GLXExt[] = {
+    { GlxExtensionInit, "GLX", &noGlxExtension },
 };
 
 static XF86ModuleVersionInfo VersRec = {
@@ -90,7 +88,7 @@ glxSetup(void *module, void *opts, int *errmaj, int *errmin)
             GlxPushProvider(provider);
     }
 
-    LoadExtension(&GLXExt, FALSE);
+    LoadExtensionList(GLXExt, ARRAY_SIZE(GLXExt), FALSE);
 
     return module;
 }
diff --git a/hw/xfree86/doc/ddxDesign.xml b/hw/xfree86/doc/ddxDesign.xml
index 7c2c20f..d1fd9af 100644
--- a/hw/xfree86/doc/ddxDesign.xml
+++ b/hw/xfree86/doc/ddxDesign.xml
@@ -5920,10 +5920,10 @@ These may be moved out of the loader at some point.
 
       <blockquote><para>
 	  <programlisting>
-    void LoadExtension(ExtensionModule *ext);
+    void LoadExtensionList(const ExtensionModule ext[]);
 	  </programlisting>
 	  <blockquote><para>
-    This registers the entry points for the extension identified by
+    This registers the entry points for the extension array identified by
     <parameter>ext</parameter>.  The <structname>ExtensionModule</structname> struct is
     defined as:
 
diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index bc6c8d0..d7229ce 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -164,10 +164,7 @@ static const ExtensionModule quartzExtensions[] = {
  */
 static void QuartzExtensionInit(void)
 {
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(quartzExtensions); i++)
-        LoadExtension(&quartzExtensions[i], TRUE);
+    LoadExtensionList(quartzExtensions, ARRAY_SIZE(quartzExtensions), TRUE);
 }
 
 /*
diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index b3ff7c0..6b5c38d 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -163,8 +163,6 @@ static const ExtensionModule xwinExtensions[] = {
 static
 void XwinExtensionInit(void)
 {
-    int i;
-
 #ifdef XWIN_GLX_WINDOWS
     if (g_fNativeGl) {
         /* install the native GL provider */
@@ -172,8 +170,7 @@ void XwinExtensionInit(void)
     }
 #endif
 
-    for (i = 0; i < ARRAY_SIZE(xwinExtensions); i++)
-        LoadExtension(&xwinExtensions[i], TRUE);
+    LoadExtensionList(xwinExtensions, ARRAY_SIZE(xwinExtensions), TRUE);
 }
 
 #if defined(DDXBEFORERESET)
diff --git a/include/extension.h b/include/extension.h
index acc6add..7c09af1 100644
--- a/include/extension.h
+++ b/include/extension.h
@@ -97,6 +97,7 @@ extern _X_EXPORT void InitExtensions(int argc, char **argv);
 
 extern _X_EXPORT void CloseDownExtensions(void);
 
-extern _X_EXPORT void LoadExtension(const ExtensionModule *ext, Bool external);
+extern _X_EXPORT void LoadExtensionList(const ExtensionModule ext[],
+                                        int listSize, Bool external);
 
 #endif                          /* EXTENSION_H */
diff --git a/mi/miinitext.c b/mi/miinitext.c
index b136818..5b45ab4 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -312,15 +312,13 @@ static void
 AddStaticExtensions(void)
 {
     static Bool listInitialised = FALSE;
-    int i;
 
     if (listInitialised)
         return;
     listInitialised = TRUE;
 
     /* Add built-in extensions to the list. */
-    for (i = 0; i < ARRAY_SIZE(staticExtensions); i++)
-        LoadExtension(&staticExtensions[i], TRUE);
+    LoadExtensionList(staticExtensions, ARRAY_SIZE(staticExtensions), TRUE);
 }
 
 void
@@ -341,7 +339,7 @@ InitExtensions(int argc, char *argv[])
 }
 
 static ExtensionModule *
-NewExtensionModule(void)
+NewExtensionModuleList(int size)
 {
     ExtensionModule *save = ExtensionModuleList;
     int n;
@@ -350,7 +348,7 @@ NewExtensionModule(void)
     if (!ExtensionModuleList)
         numExtensionModules = 0;
 
-    n = numExtensionModules + 1;
+    n = numExtensionModules + size;
     ExtensionModuleList = realloc(ExtensionModuleList,
                                   n * sizeof(ExtensionModule));
     if (ExtensionModuleList == NULL) {
@@ -358,29 +356,35 @@ NewExtensionModule(void)
         return NULL;
     }
     else {
-        numExtensionModules++;
-        return ExtensionModuleList + (numExtensionModules - 1);
+        numExtensionModules += size;
+        return ExtensionModuleList + (numExtensionModules - size);
     }
 }
 
 void
-LoadExtension(const ExtensionModule * e, Bool builtin)
+LoadExtensionList(const ExtensionModule ext[], int size, Bool builtin)
 {
     ExtensionModule *newext;
+    const char *msg;
+    int i;
 
     /* Make sure built-in extensions get added to the list before those
      * in modules. */
     AddStaticExtensions();
 
-    if (!(newext = NewExtensionModule()))
+    if (!(newext = NewExtensionModuleList(size)))
         return;
 
     if (builtin)
-        ErrorF("Initializing built-in extension %s\n", e->name);
+        msg = "Initializing built-in";
     else
-        ErrorF("Loading extension %s\n", e->name);
+        msg = "Loading";
 
-    newext->name = e->name;
-    newext->initFunc = e->initFunc;
-    newext->disablePtr = e->disablePtr;
+    for (i = 0; i < size; i++, newext++) {
+        ErrorF("%s extension %s\n", msg, ext[i].name);
+
+        newext->name = ext[i].name;
+        newext->initFunc = ext[i].initFunc;
+        newext->disablePtr = ext[i].disablePtr;
+    }
 }
commit 78167a98a8631ee3fad145ddc051ceb8487b9683
Author: Adam Jackson <ajax at redhat.com>
Date:   Fri Nov 8 09:44:24 2013 -0500

    xkb: Restore XkbCopyDeviceKeymap
    
    Removed in d35a02a767017f13db4bd4742eef49293d5a30ea, tigervnc 1.2.80 and
    xf86-video-nested need it for now.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index a80e119..229de21 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -824,6 +824,9 @@ extern _X_EXPORT void XkbSendNewKeyboardNotify(DeviceIntPtr /* kbd */ ,
 extern Bool XkbCopyKeymap(XkbDescPtr /* dst */ ,
                           XkbDescPtr /* src */ );
 
+extern _X_EXPORT Bool XkbCopyDeviceKeymap(DeviceIntPtr /* dst */,
+					  DeviceIntPtr /* src */);
+
 extern _X_EXPORT Bool XkbDeviceApplyKeymap(DeviceIntPtr /* dst */ ,
                                            XkbDescPtr /* src */ );
 
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 6cf6e79..c14a790 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -2027,6 +2027,12 @@ XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc)
     return ret;
 }
 
+Bool
+XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src)
+{
+    return XkbDeviceApplyKeymap(dst, src->key->xkbInfo->desc);
+}
+
 int
 XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
 {
commit 215f3d2e0f2a4ef6fc2f2c08fb991e1f00b747c8
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Mar 19 20:46:41 2014 -0700

    os: Add AddClientOnOpenFD() to create a new client for an file descriptor
    
    When the Xwayland server is socket-activated, we need to connect and
    initialize the window manager before the activating client gets to
    proceed with connecting.  We do this by passing a socket file
    descriptor for the window manager connection to the Xwayland server,
    which then uses this new function to set it up as an X client.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/include/os.h b/include/os.h
index 90229e6..d26e399 100644
--- a/include/os.h
+++ b/include/os.h
@@ -168,6 +168,8 @@ extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client */ );
 
 extern _X_EXPORT void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
 
+extern _X_EXPORT Bool AddClientOnOpenFD(int /* fd */ );
+
 extern _X_EXPORT CARD32 GetTimeInMillis(void);
 extern _X_EXPORT CARD64 GetTimeInMicros(void);
 
diff --git a/os/connection.c b/os/connection.c
index b50f9e9..b3640b8 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -1312,3 +1312,30 @@ ListenOnOpenFD(int fd, int noxauth)
     XdmcpReset();
 #endif
 }
+
+/* based on TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) */
+Bool
+AddClientOnOpenFD(int fd)
+{
+    XtransConnInfo ciptr;
+    CARD32 connect_time;
+    char port[20];
+
+    snprintf(port, sizeof(port), ":%d", atoi(display));
+    ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
+    if (ciptr == NULL)
+        return FALSE;
+
+    _XSERVTransSetOption(ciptr, TRANS_NONBLOCKING, 1);
+    ciptr->flags |= TRANS_NOXAUTH;
+
+    connect_time = GetTimeInMillis();
+
+    if (!AllocNewConnection(ciptr, fd, connect_time)) {
+        ErrorConnMax(ciptr);
+        _XSERVTransClose(ciptr);
+        return FALSE;
+    }
+
+    return TRUE;
+}
commit d415b9d69fdaab4ce3fc05d3d26b2d8413403aa4
Author: Emil Velikov <emil.l.velikov at gmail.com>
Date:   Thu Sep 26 20:16:31 2013 +0100

    miinitext: avoid allocating a sentinel ExtensionModule
    
    With all the logic now in place there is no need to allocate a separate
    ExtensionModule to be used as a sentinel.
    
    Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/mi/miinitext.c b/mi/miinitext.c
index ce2e4bc..b136818 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -331,7 +331,7 @@ InitExtensions(int argc, char *argv[])
 
     AddStaticExtensions();
 
-    for (i = 0; ExtensionModuleList[i].name != NULL; i++) {
+    for (i = 0; i < numExtensionModules; i++) {
         ext = &ExtensionModuleList[i];
         if (ext->initFunc != NULL &&
             (ext->disablePtr == NULL || !*ext->disablePtr)) {
@@ -352,14 +352,13 @@ NewExtensionModule(void)
 
     n = numExtensionModules + 1;
     ExtensionModuleList = realloc(ExtensionModuleList,
-                                  (n + 1) * sizeof(ExtensionModule));
+                                  n * sizeof(ExtensionModule));
     if (ExtensionModuleList == NULL) {
         ExtensionModuleList = save;
         return NULL;
     }
     else {
         numExtensionModules++;
-        ExtensionModuleList[numExtensionModules].name = NULL;
         return ExtensionModuleList + (numExtensionModules - 1);
     }
 }
commit b421ac8e026f464fdba2082aaedc00c19fb8b6c7
Author: Emil Velikov <emil.l.velikov at gmail.com>
Date:   Thu Sep 26 20:11:40 2013 +0100

    miinitext: constify staticExtensions
    
    The array is readonly and should not be tampered with.
    
    Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/mi/miinitext.c b/mi/miinitext.c
index 099ac42..ce2e4bc 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -234,7 +234,7 @@ EnableDisableExtensionError(const char *name, Bool enable)
 }
 
 /* List of built-in (statically linked) extensions */
-static ExtensionModule staticExtensions[] = {
+static const ExtensionModule staticExtensions[] = {
     {GEExtensionInit, "Generic Event Extension", &noGEExtension},
     {ShapeExtensionInit, "SHAPE", NULL},
 #ifdef MITSHM
commit 5ff34b5a0b3b333bf0f0334717cc8630cc785510
Author: Emil Velikov <emil.l.velikov at gmail.com>
Date:   Thu Sep 26 20:08:56 2013 +0100

    miinitext: drop sentinel detection during LoadExtension
    
    All the sentinels from the extension lists were removed, thus the only
    case were this would trigger is when the code is broken badly.
    
    Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/mi/miinitext.c b/mi/miinitext.c
index 9d5125e..099ac42 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -369,9 +369,6 @@ LoadExtension(const ExtensionModule * e, Bool builtin)
 {
     ExtensionModule *newext;
 
-    if (e == NULL || e->name == NULL)
-        return;
-
     /* Make sure built-in extensions get added to the list before those
      * in modules. */
     AddStaticExtensions();
commit 6fea450d41a03d32c10c7da162dfaadd8ead4ece
Author: Emil Velikov <emil.l.velikov at gmail.com>
Date:   Thu Sep 26 20:08:16 2013 +0100

    miinitext: move AddStaticExtensions() to LoadExtension()
    
    Separate the function from NewExtensionModule() as the former does
    only memory reallocation. No functional change.
    
    Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/mi/miinitext.c b/mi/miinitext.c
index 67511b8..9d5125e 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -346,10 +346,6 @@ NewExtensionModule(void)
     ExtensionModule *save = ExtensionModuleList;
     int n;
 
-    /* Make sure built-in extensions get added to the list before those
-     * in modules. */
-    AddStaticExtensions();
-
     /* Sanity check */
     if (!ExtensionModuleList)
         numExtensionModules = 0;
@@ -376,6 +372,10 @@ LoadExtension(const ExtensionModule * e, Bool builtin)
     if (e == NULL || e->name == NULL)
         return;
 
+    /* Make sure built-in extensions get added to the list before those
+     * in modules. */
+    AddStaticExtensions();
+
     if (!(newext = NewExtensionModule()))
         return;
 
commit bf087659f0fb747c471e26c5b287c35877818040
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sat Mar 22 14:30:04 2014 -0700

    Add necessary headers for major()/minor() on Solaris to xf86Xinput.c
    
    Without these, after commit fdb4ec86c29d85c, it fails to build on Solaris,
    with errors of:
    xf86Xinput.c: In function 'xf86stat':
    xf86Xinput.c:816:5: error: implicit declaration of function 'major' [-Werror=implicit-function-declaration]
    xf86Xinput.c:817:5: error: implicit declaration of function 'minor' [-Werror=implicit-function-declaration]
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 20c080c..a75ba8f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -133,7 +133,8 @@ AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"
 
 AC_HEADER_DIRENT
 AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h sys/utsname.h])
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h \
+ fnmatch.h sys/mkdev.h sys/utsname.h])
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index a367ae3..bc6b73f 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -81,8 +81,12 @@
 
 #include <stdarg.h>
 #include <stdint.h>             /* for int64_t */
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#ifdef HAVE_SYS_MKDEV_H
+#include <sys/mkdev.h>          /* for major() & minor() on Solaris */
+#endif
 
 #include "mi.h"
 
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 487d7ad..77a1aae 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -118,6 +118,9 @@
 /* Have execinfo.h */
 #undef HAVE_EXECINFO_H
 
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+#undef HAVE_SYS_MKDEV_H
+
 /* Path to text files containing PCI IDs */
 #undef PCI_TXT_IDS_PATH
 
commit d9fdae5f4a648a10653e18dbc602646f3e22e522
Merge: 99bee6c 0e5d299
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 22 14:09:00 2014 -0700

    Merge remote-tracking branch 'jturney/master'

commit 99bee6c0549b36ef15f625bab3997cbd70c7b879
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Fri Jan 17 09:54:01 2014 -0500

    Default font path: remove the check for ${sysconfdir}/X11/fontpath.d
    
    The location ${sysconfdir}/X11/fontpath.d is unknown at configuration time
    (only at make time) as evidenced by the configuration output:
    
        checking for ${prefix}/etc/X11/fontpath.d... no
    
    Unlike font-util for the X fonts, there is no mechanism to query where
    fontpath.d is. Fedora have chosen /etc/X11 and others have followed, but this
    is not a standard. It might also be installed at another location, it may or may
    not be under the xserver installation prefix. We just don't know. Debian does
    not use this at all.
    
    Distros are using --with-default-path when they support fontpath.d, so they
    never relied on the server default as it never worked.
    
    The patch essentially is a noop, which leaves the door open for anyone who
    could potentially provide a reliable implementation of choosing fontpath.d
    when applicable.
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 749fa84..20c080c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -491,17 +491,14 @@ XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1)
 XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi)
 XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi)
 
-dnl Uses --default-font-path if set, otherwise checks for /etc/X11/fontpath.d,
-dnl otherwise uses standard subdirectories of FONTROOTDIR. When cross
-dnl compiling, assume default font path uses standard FONTROOTDIR directories.
+dnl Uses --with-default-font-path if set, otherwise uses standard
+dnl subdirectories of FONTROOTDIR. Some distros set the default font path to
+dnl "catalogue:/etc/X11/fontpath.d,built-ins"
 DEFAULT_FONT_PATH="${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/"
-if test "$cross_compiling" != yes; then
-	AC_CHECK_FILE([${sysconfdir}/X11/fontpath.d],
-		[DEFAULT_FONT_PATH='catalogue:${sysconfdir}/X11/fontpath.d'],
-		[case $host_os in
-			darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;;
-		esac])
-fi
+case $host_os in
+    darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;;
+esac
+
 AC_ARG_WITH(default-font-path, AS_HELP_STRING([--with-default-font-path=PATH], [Comma separated list of font dirs]),
 				[ FONTPATH="$withval" ],
 				[ FONTPATH="${DEFAULT_FONT_PATH}" ])
commit 1782316744866a181ed92486bb4dca6ac46d40bd
Merge: 4fb31e4 2b77b20
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 22 13:46:15 2014 -0700

    Merge remote-tracking branch 'jwrdecoede/for-keith'

commit 0e5d2996ac872aca5995897fc518bdf9116bd246
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Sep 11 13:36:18 2013 +0100

    hw/xwin: Fix WM_ENDSESSION crash on x86_64
    
    We need to include xwin-config.h into winmsgwindow.c, so that _XSERVER64 is
    defined, so that the layout of ScreenRec type is correct, so that it's privates
    can be accessed correctly, so that the WM_GIVEUP message can be sent to the
    screen window.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmsgwindow.c b/hw/xwin/winmsgwindow.c
index 8067c69..59f1da5 100644
--- a/hw/xwin/winmsgwindow.c
+++ b/hw/xwin/winmsgwindow.c
@@ -22,6 +22,10 @@
  *
  */
 
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
 #include "win.h"
 
 /*
commit 896b53ffa72d91d7d604967028291525562b60dd
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Jun 16 13:55:51 2013 +0100

    hw/xwin: Improve NET_WM_ICON validation
    
    Check that we don't overrun the end of the property data while converting icons
    
    See http://cygwin.com/ml/cygwin-xfree/2013-06/msg00040.html for testcase.
    
    Also, some warning fixes in winXIconToHICON()
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowicons.c b/hw/xwin/winmultiwindowicons.c
index 0531ad6..93d389d 100644
--- a/hw/xwin/winmultiwindowicons.c
+++ b/hw/xwin/winmultiwindowicons.c
@@ -372,13 +372,12 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
     unsigned char *mask, *image = NULL, *imageMask;
     unsigned char *dst, *src;
     int planes, bpp, i;
-    int biggest_size = 0;
+    unsigned int biggest_size = 0;
     HDC hDC;
     ICONINFO ii;
     XWMHints *hints;
     HICON hIcon = NULL;
     uint32_t *biggest_icon = NULL;
-
     static Atom _XA_NET_WM_ICON;
     static int generation;
     uint32_t *icon, *icon_data = NULL;
@@ -405,10 +404,25 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
         (icon_data != NULL)) {
         for (icon = icon_data; icon < &icon_data[size] && *icon;
              icon = &icon[icon[0] * icon[1] + 2]) {
-            /* Find an exact match to the size we require...  */
+            winDebug("winXIconToHICON: %u x %u NetIcon\n", icon[0], icon[1]);
+
+            /* Icon data size will overflow an int and thus is bigger than the
+               property can possibly be */
+            if ((INT_MAX/icon[0]) < icon[1]) {
+                winDebug("winXIconToHICON: _NET_WM_ICON icon data size overflow\n");
+                break;
+            }
+
+            /* Icon data size is bigger than amount of data remaining */
+            if (&icon[icon[0] * icon[1] + 2] > &icon_data[size]) {
+                winDebug("winXIconToHICON: _NET_WM_ICON data is malformed\n");
+                break;
+            }
+
+            /* Found an exact match to the size we require...  */
             if (icon[0] == iconSize && icon[1] == iconSize) {
-                winDebug("winXIconToHICON: found %lu x %lu NetIcon\n", icon[0],
-                         icon[1]);
+                winDebug("winXIconToHICON: selected %d x %d NetIcon\n",
+                         iconSize, iconSize);
                 hIcon = NetWMToWinIcon(bpp, icon);
                 break;
             }
@@ -421,7 +435,7 @@ winXIconToHICON(Display * pDisplay, Window id, int iconSize)
 
         if (!hIcon && biggest_icon) {
             winDebug
-                ("winXIconToHICON: selected %lu x %lu NetIcon for scaling to %u x %u\n",
+                ("winXIconToHICON: selected %u x %u NetIcon for scaling to %d x %d\n",
                  biggest_icon[0], biggest_icon[1], iconSize, iconSize);
 
             hIcon = NetWMToWinIcon(bpp, biggest_icon);
commit ab61d070024a4776f011e71d762d4c6c0cf58b12
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Mar 31 18:29:07 2013 +0100

    hw/xwin: Remove obsolete control handling for About dialog
    
    Remove the unused, cygwin-specific handling for ChangeLog, UG and CG buttons in
    the About... Dialog.  The buttons themselves were removed in commmit
    34269a90ea2087f883f5dc8805894fc4998e4b81.
    
    Also remove those window control IDs which are now obsolete.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/windialogs.c b/hw/xwin/windialogs.c
index 054ee95..c9af0e2 100644
--- a/hw/xwin/windialogs.c
+++ b/hw/xwin/windialogs.c
@@ -574,10 +574,7 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
         winInitDialog(hwndDialog);
 
         /* Override the URL buttons */
-        winOverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
         winOverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
-        winOverrideURLButton(hwndDialog, ID_ABOUT_UG);
-        winOverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
 
         return TRUE;
 
@@ -608,30 +605,10 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
             PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
 
             /* Restore window procedures for URL buttons */
-            winUnoverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
             winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
-            winUnoverrideURLButton(hwndDialog, ID_ABOUT_UG);
-            winUnoverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
 
             return TRUE;
 
-        case ID_ABOUT_CHANGELOG:
-        {
-            INT_PTR iReturn;
-
-            const char *pszWinPath = "http://x.cygwin.com/"
-                "devel/server/changelog.html";
-
-            iReturn = (INT_PTR) ShellExecute(NULL,
-                                         "open",
-                                         pszWinPath, NULL, NULL, SW_MAXIMIZE);
-            if (iReturn < 32) {
-                ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_CHANGELOG - "
-                       "ShellExecute failed: %d\n", (int)iReturn);
-            }
-        }
-            return TRUE;
-
         case ID_ABOUT_WEBSITE:
         {
             const char *pszPath = __VENDORDWEBSUPPORT__;
@@ -647,36 +624,6 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
             }
         }
             return TRUE;
-
-        case ID_ABOUT_UG:
-        {
-            const char *pszPath = "http://x.cygwin.com/docs/ug/";
-            INT_PTR iReturn;
-
-            iReturn = (INT_PTR) ShellExecute(NULL,
-                                         "open",
-                                         pszPath, NULL, NULL, SW_MAXIMIZE);
-            if (iReturn < 32) {
-                ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_UG - "
-                       "ShellExecute failed: %d\n", (int)iReturn);
-            }
-        }
-            return TRUE;
-
-        case ID_ABOUT_FAQ:
-        {
-            const char *pszPath = "http://x.cygwin.com/docs/faq/";
-            INT_PTR iReturn;
-
-            iReturn = (INT_PTR) ShellExecute(NULL,
-                                         "open",
-                                         pszPath, NULL, NULL, SW_MAXIMIZE);
-            if (iReturn < 32) {
-                ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_FAQ - "
-                       "ShellExecute failed: %d\n", (int)iReturn);
-            }
-        }
-            return TRUE;
         }
         break;
 
@@ -690,10 +637,7 @@ winAboutDlgProc(HWND hwndDialog, UINT message, WPARAM wParam, LPARAM lParam)
         PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
 
         /* Restore window procedures for URL buttons */
-        winUnoverrideURLButton(hwndDialog, ID_ABOUT_CHANGELOG);
         winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
-        winUnoverrideURLButton(hwndDialog, ID_ABOUT_UG);
-        winUnoverrideURLButton(hwndDialog, ID_ABOUT_FAQ);
 
         return TRUE;
     }
diff --git a/hw/xwin/winresource.h b/hw/xwin/winresource.h
index a14d402..afbf9f2 100644
--- a/hw/xwin/winresource.h
+++ b/hw/xwin/winresource.h
@@ -44,9 +44,6 @@
 #define ID_APP_ALWAYS_ON_TOP	202
 #define ID_APP_ABOUT		203
 
-#define ID_ABOUT_UG		300
-#define ID_ABOUT_FAQ		301
-#define ID_ABOUT_CHANGELOG	302
 #define ID_ABOUT_WEBSITE	303
 
 #endif
commit 3b4d472b72601922bac264283eb6b611d8d524fc
Author: Oliver Schmidt <oschmidt-mailinglists at gmx.de>
Date:   Wed Sep 7 14:00:56 2011 +0100

    hw/xwin: Minimize redraw events after resizing/moving windows in multiwindow mode
    
    In multiwindow mode the modal moving/resizing of windows causes a lot of redraw
    events to be sent to the X clients after the user releases the mouse button.
    During the moving/resizing client windows are not redrawn as long as the mouse
    button is pressed, but all redraw/resizing events are queued and executed step
    after step after the moving/resizing ends.
    
    Some clients collect and combine multiple redraw or resizing events, other
    clients (e.g. xterm) simply execute each redraw or sizing event.
    
    The enclosed patch minimizes the events for clients to only one event after the
    user releases the mouse button to end the moving/resizing. This improves the
    user experience and reduces strange screen flickerings, especially on slow
    platforms.
    
    The enclosed patch modifies winmultiwindowwndproc.c such that the windows events
    WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE that are sent by Windows when the modal
    window resizing/moving begins or ends are considered. Only after WM_EXITSIZEMOVE
    is the redraw/resizing executed.
    
    Signed-off-by: Oliver Schmidt <oschmidt-mailinglists at gmx.de>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index 2d57014..17823ba 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -316,6 +316,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     static Bool s_fTracking = FALSE;
     Bool needRestack = FALSE;
     LRESULT ret;
+    static Bool hasEnteredSizeMove = FALSE;
 
 #if CYGDEBUG
     winDebugWin32Message("winTopLevelWindowProc", hwnd, message, wParam,
@@ -872,7 +873,9 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
     case WM_MOVE:
         /* Adjust the X Window to the moved Windows window */
-        winAdjustXWindow(pWin, hwnd);
+        if (!hasEnteredSizeMove)
+            winAdjustXWindow(pWin, hwnd);
+        /* else: Wait for WM_EXITSIZEMOVE */
         return 0;
 
     case WM_SHOWWINDOW:
@@ -1005,6 +1008,16 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          */
         break;
 
+    case WM_ENTERSIZEMOVE:
+        hasEnteredSizeMove = TRUE;
+        return 0;
+
+    case WM_EXITSIZEMOVE:
+        /* Adjust the X Window to the moved Windows window */
+        hasEnteredSizeMove = FALSE;
+        winAdjustXWindow(pWin, hwnd);
+        return 0;
+
     case WM_SIZE:
         /* see dix/window.c */
 #if CYGWINDOWING_DEBUG
@@ -1029,8 +1042,11 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                (int) (GetTickCount()));
     }
 #endif
-        /* Adjust the X Window to the moved Windows window */
-        winAdjustXWindow(pWin, hwnd);
+        if (!hasEnteredSizeMove) {
+            /* Adjust the X Window to the moved Windows window */
+            winAdjustXWindow(pWin, hwnd);
+        }
+        /* else: wait for WM_EXITSIZEMOVE */
         return 0;               /* end of WM_SIZE handler */
 
     case WM_STYLECHANGING:
commit 03e1cc6f250a3f5cf17b34639adbbc9850c681cd
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Nov 7 20:54:10 2011 +0000

    hw/xwin: Add '@<WM_CLIENT_MACHINE>' to window name when it's useful to do so
    
    Enhance GetWindowName() so it appends the result of XGetWMClientMachine() when
    it is available and useful to do so
    
    Add -hostintitle option to control this behaviour.  Add documentation for this
    option to man page and -help text.
    
    Also, fix warning in UpdateName()
    
    v2: Provide a HOST_NAME_MAX definition for MinGW
    v3: Use '@host' rather than ' (on host)'. Don't add host if it's already in the
    title.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Yaakov Selkowitz <yselkowitz at users.sourceforge.net>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index 04015cd..b3ff7c0 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -786,6 +786,9 @@ winUseMsg(void)
 
     ErrorF("-fullscreen\n" "\tRun the server in fullscreen mode.\n");
 
+    ErrorF("-hostintitle\n"
+           "\tIn multiwindow mode, add remote host names to window titles.\n");
+
     ErrorF("-ignoreinput\n" "\tIgnore keyboard and mouse input.\n");
 
 #ifdef XWIN_MULTIWINDOWEXTWM
diff --git a/hw/xwin/man/XWin.man b/hw/xwin/man/XWin.man
index 18ee667..c71f6a1 100644
--- a/hw/xwin/man/XWin.man
+++ b/hw/xwin/man/XWin.man
@@ -165,6 +165,12 @@ The maximum dimensions of the screen are the dimensions of the \fIWindows\fP vir
 on its own is equivalent to \fB\-resize=randr\fP
 .RE
 
+.SH OPTIONS FOR MULTIWINDOW MODE
+.TP 8
+.B \-hostintitle
+Add the host name to the window title for X applications which are running
+on remote hosts, when that information is available and it's useful to do so.
+
 .SH OPTIONS CONTROLLING WINDOWS INTEGRATION
 .TP 8
 .B \-[no]clipboard
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index d281322..b9ad294 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -78,6 +78,7 @@ Bool g_fNoHelpMessageBox = FALSE;
 Bool g_fSoftwareCursor = FALSE;
 Bool g_fSilentDupError = FALSE;
 Bool g_fNativeGl = TRUE;
+Bool g_fHostInTitle = FALSE;
 pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
 
 #ifdef XWIN_CLIPBOARD
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index 58a919c..60c00da 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -54,6 +54,7 @@ extern Bool g_fXdmcpEnabled;
 extern Bool g_fNoHelpMessageBox;
 extern Bool g_fSilentDupError;
 extern Bool g_fNativeGl;
+extern Bool g_fHostInTitle;
 
 extern HWND g_hDlgDepthChange;
 extern HWND g_hDlgExit;
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index ec577a7..618e381 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -60,6 +60,7 @@
 #include "window.h"
 #include "pixmapstr.h"
 #include "windowstr.h"
+#include "winglobals.h"
 
 #ifdef XWIN_MULTIWINDOWEXTWM
 #include <X11/extensions/windowswmstr.h>
@@ -69,6 +70,10 @@
 #define WINDOWSWM_NATIVE_HWND "_WINDOWSWM_NATIVE_HWND"
 #endif
 
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif
+
 extern void winDebug(const char *format, ...);
 extern void winReshapeMultiWindow(WindowPtr pWin);
 extern void winUpdateRgnMultiWindow(WindowPtr pWin);
@@ -430,7 +435,10 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
 {
     int nResult;
     XTextProperty xtpWindowName;
+    XTextProperty xtpClientMachine;
     char *pszWindowName;
+    char *pszClientMachine;
+    char hostname[HOST_NAME_MAX + 1];
 
 #if CYGMULTIWINDOW_DEBUG
     ErrorF("GetWindowName\n");
@@ -450,6 +458,41 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
 
     pszWindowName = Xutf8TextPropertyToString(pDisplay, &xtpWindowName);
     XFree(xtpWindowName.value);
+
+    if (g_fHostInTitle) {
+        /* Try to get client machine name */
+        nResult = XGetWMClientMachine(pDisplay, iWin, &xtpClientMachine);
+        if (nResult && xtpClientMachine.value && xtpClientMachine.nitems) {
+            pszClientMachine =
+                Xutf8TextPropertyToString(pDisplay, &xtpClientMachine);
+            XFree(xtpClientMachine.value);
+
+            /*
+               If we have a client machine name
+               and it's not the local host name
+               and it's not already in the window title...
+             */
+            if (strlen(pszClientMachine) &&
+                !gethostname(hostname, HOST_NAME_MAX + 1) &&
+                strcmp(hostname, pszClientMachine) &&
+                (strstr(pszWindowName, pszClientMachine) == 0)) {
+                /* ... add '@<clientmachine>' to end of window name */
+                *ppWindowName =
+                    malloc(strlen(pszWindowName) +
+                           strlen(pszClientMachine) + 2);
+                strcpy(*ppWindowName, pszWindowName);
+                strcat(*ppWindowName, "@");
+                strcat(*ppWindowName, pszClientMachine);
+
+                free(pszWindowName);
+                free(pszClientMachine);
+
+                return;
+            }
+        }
+    }
+
+    /* otherwise just return the window name */
     *ppWindowName = pszWindowName;
 }
 
diff --git a/hw/xwin/winprocarg.c b/hw/xwin/winprocarg.c
index 858be4a..f2bf05b 100644
--- a/hw/xwin/winprocarg.c
+++ b/hw/xwin/winprocarg.c
@@ -1074,6 +1074,11 @@ ddxProcessArgument(int argc, char *argv[], int i)
         return 1;
     }
 
+    if (IS_OPTION("-hostintitle")) {
+        g_fHostInTitle = TRUE;
+        return 1;
+    }
+
     return 0;
 }
 
commit 6804acfe4fabc8ff8491bbc7edb6260440d3d4d3
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:44:54 2014 +0000

    hw/xwin: Remove prototype for non-existent winMWExtWMUpdateIcon()
    
    winMWExtWMUpdateIcon() was removed in commit 527cf13135cfd279733060e0028bbfbe02be5167
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 80fc504..a738a59 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -1336,9 +1336,6 @@ void
  winMWExtWMMoveResizeXWindow(WindowPtr pWin, int x, int y, int w, int h);
 
 void
- winMWExtWMUpdateIcon(Window id);
-
-void
 
 winMWExtWMUpdateWindowDecoration(win32RootlessWindowPtr pRLWinPriv,
                                  winScreenInfoPtr pScreenInfo);
commit 7fb5d765ba1e28eb775b847cef3d6079eba3bac1
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:40:43 2014 +0000

    hw/xwin: Use AllocDevicePair()
    
    Use AllocDevicePair() rather than allocating Windows keyboard and pointer
    devices individually.
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/InitInput.c b/hw/xwin/InitInput.c
index 36346b7..38203c9 100644
--- a/hw/xwin/InitInput.c
+++ b/hw/xwin/InitInput.c
@@ -108,10 +108,11 @@ InitInput(int argc, char *argv[])
     }
 #endif
 
-    g_pwinPointer = AddInputDevice(serverClient, winMouseProc, TRUE);
-    g_pwinKeyboard = AddInputDevice(serverClient, winKeybdProc, TRUE);
-    g_pwinPointer->name = strdup("Windows mouse");
-    g_pwinKeyboard->name = strdup("Windows keyboard");
+    if (AllocDevicePair(serverClient, "Windows",
+                        &g_pwinPointer, &g_pwinKeyboard,
+                        winMouseProc, winKeybdProc,
+                        FALSE) != Success)
+        FatalError("InitInput - Failed to allocate slave devices.\n");
 
     mieqInit();
 
commit 061e5eba00a9a0dc27ff76946dc5f77004fc6a56
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:36:59 2014 +0000

    hw/xwin: Consistently use 'L' for long int constants
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 9f12521..ec577a7 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -1618,10 +1618,10 @@ winDeinitMultiWindowWM(void)
 }
 
 /* Windows window styles */
-#define HINT_NOFRAME	(1l<<0)
+#define HINT_NOFRAME	(1L<<0)
 #define HINT_BORDER	(1L<<1)
-#define HINT_SIZEBOX	(1l<<2)
-#define HINT_CAPTION	(1l<<3)
+#define HINT_SIZEBOX	(1L<<2)
+#define HINT_CAPTION	(1L<<3)
 #define HINT_NOMAXIMIZE (1L<<4)
 #define HINT_NOMINIMIZE (1L<<5)
 #define HINT_NOSYSMENU  (1L<<6)
commit 46df614784cbbffcf6368859285e949010f1ceb8
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:36:24 2014 +0000

    hw/xwin: Remove an unneeded include
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c
index 0b62696..660a78f 100644
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -39,7 +39,6 @@
 #include <winuser.h>
 #define _WINDOWSWM_SERVER_
 #include <X11/extensions/windowswmstr.h>
-#include "dixevents.h"
 #include "winmultiwindowclass.h"
 #include <X11/Xatom.h>
 
commit d48749492dc492fd7430ffdfd29842153618f778
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:34:04 2014 +0000

    hw/xwin: Use boolean AND rather than bitwise AND in WIN_POLLING_MOUSE_TIMER_ID
    
    For clarity, use boolean AND rather than bitwise AND in
    WIN_POLLING_MOUSE_TIMER_ID processing.
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c
index c73a75c..bee223d 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -955,11 +955,11 @@ winWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             wShift = (GetKeyState(VK_SHIFT) & 0x8000) ? MK_SHIFT : 0;
             wCtrl = (GetKeyState(VK_CONTROL) & 0x8000) ? MK_CONTROL : 0;
             lPos = MAKELPARAM(point.x, point.y);
-            if (g_fButton[0] & !wL)
+            if (g_fButton[0] && !wL)
                 PostMessage(hwnd, WM_LBUTTONUP, wCtrl | wM | wR | wShift, lPos);
-            if (g_fButton[1] & !wM)
+            if (g_fButton[1] && !wM)
                 PostMessage(hwnd, WM_MBUTTONUP, wCtrl | wL | wR | wShift, lPos);
-            if (g_fButton[2] & !wR)
+            if (g_fButton[2] && !wR)
                 PostMessage(hwnd, WM_RBUTTONUP, wCtrl | wL | wM | wShift, lPos);
         }
         }
commit 80ac4a85d56130d09bbc72ed071759a361ded689
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:23:16 2014 +0000

    hw/xwin: Fix declaration after statement warning in ddxGiveUp()
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index 9413350..04015cd 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -271,10 +271,10 @@ ddxGiveUp(enum ExitCode error)
     PostQuitMessage(0);
 
     {
-        winDebug("ddxGiveUp - Releasing termination mutex\n");
-
         int iReturn = pthread_mutex_unlock(&g_pmTerminating);
 
+        winDebug("ddxGiveUp - Releasing termination mutex\n");
+
         if (iReturn != 0) {
             ErrorF("winMsgWindowProc - pthread_mutex_unlock () failed: %d\n",
                    iReturn);
commit cf59f4888e202c6a68176bd3de1f837ca8480370
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Mar 14 15:09:24 2014 +0000

    hw/xwin: Fix typo in comment
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index abb87ee..2d57014 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -837,7 +837,7 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
         break;
 
     case WM_CLOSE:
-        /* Removep AppUserModelID property */
+        /* Remove AppUserModelID property */
         winSetAppUserModelID(hwnd, NULL);
         /* Branch on if the window was killed in X already */
         if (pWinPriv->fXKilled) {
commit 561bca469d3ade1ff14faddaf70bf12dcdc6aa74
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Mar 13 22:38:43 2014 +0000

    hw/xwin: Fix const discarded warning in winGenerateAuthorization()
    
    Fix const discarded warning in winGenerateAuthorization() in !XCSECURITY case
    
    In function ‘winGenerateAuthorization’:
    hw/xwin/winauth.c:123:38: warning: passing argument 2 of ‘GenerateAuthorization’ discards ‘const’ qualifier from pointer target type [enabled by default]
    hw/xwin/winauth.c:99:1: note: expected ‘char *’ but argument is of type ‘const char *’
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winauth.c b/hw/xwin/winauth.c
index a6a7366..7efa1c0 100644
--- a/hw/xwin/winauth.c
+++ b/hw/xwin/winauth.c
@@ -97,9 +97,9 @@ MitGenerateCookie(unsigned data_length,
 static
     XID
 GenerateAuthorization(unsigned name_length,
-                      char *name,
+                      const char *name,
                       unsigned data_length,
-                      char *data,
+                      const char *data,
                       unsigned *data_length_return, char **data_return)
 {
     return MitGenerateCookie(data_length, data,
commit 44fe1b8ea284df6bbaef67e246016d104665b2fe
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Mar 19 14:03:13 2014 -0700

    os: Add a mechanism to prevent creating any listen sockets
    
    A socket-activated server will receive its listening sockets from the
    parent process and should not create its own sockets.  This patch
    introduces a NoListen flag that can be set by a DDX to prevent
    the server from creating the sockets.  When NoListen is enabled, we
    also disable the server lock checking, since the parent process is
    responsible for checking the lock before picking the display name and
    creating the sockets.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/include/opaque.h b/include/opaque.h
index 73d40c3..7ec1d85 100644
--- a/include/opaque.h
+++ b/include/opaque.h
@@ -74,5 +74,6 @@ extern _X_EXPORT Bool whiteRoot;
 extern _X_EXPORT Bool bgNoneRoot;
 
 extern _X_EXPORT Bool CoreDump;
+extern _X_EXPORT Bool NoListenAll;
 
 #endif                          /* OPAQUE_H */
diff --git a/os/connection.c b/os/connection.c
index 400c542..b50f9e9 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -138,6 +138,7 @@ fd_set OutputPending;           /* clients with reply/event data ready to go */
 int MaxClients = 0;
 Bool NewOutputPending;          /* not yet attempted to write some new output */
 Bool AnyClientsWriteBlocked;    /* true if some client blocked on write */
+Bool NoListenAll;               /* Don't establish any listening sockets */
 
 static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
 Bool RunFromSigStopParent;      /* send SIGSTOP to our own process; Upstart (or
@@ -406,7 +407,10 @@ CreateWellKnownSockets(void)
     /* display is initialized to "0" by main(). It is then set to the display
      * number if specified on the command line, or to NULL when the -displayfd
      * option is used. */
-    if (display) {
+    if (NoListenAll) {
+        ListenTransCount = 0;
+    }
+    else if (display) {
         if (TryCreateSocket(atoi(display), &partial) &&
             ListenTransCount >= 1)
             if (!PartialNetwork && partial)
@@ -440,9 +444,10 @@ CreateWellKnownSockets(void)
             DefineSelf (fd);
     }
 
-    if (!XFD_ANYSET(&WellKnownConnections))
+    if (!XFD_ANYSET(&WellKnownConnections) && !NoListenAll)
         FatalError
             ("Cannot establish any listening sockets - Make sure an X server isn't already running");
+
 #if !defined(WIN32)
     OsSignal(SIGPIPE, SIG_IGN);
     OsSignal(SIGHUP, AutoResetServer);
diff --git a/os/utils.c b/os/utils.c
index 497779b..c513968 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -270,7 +270,7 @@ LockServer(void)
     int len;
     char port[20];
 
-    if (nolock)
+    if (nolock || NoListenAll)
         return;
     /*
      * Path names
@@ -390,7 +390,7 @@ LockServer(void)
 void
 UnlockServer(void)
 {
-    if (nolock)
+    if (nolock || NoListenAll)
         return;
 
     if (!StillLocking) {
commit 62d584d63190c6c8cef5fd49d87b1cb29358a434
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Tue Mar 18 22:05:58 2014 -0700

    os: Always compile ListenOnOpenFD() and export it
    
    This function was written to allow the X server to inherit the listen
    socket from launchd on OS X.  The code is not specific to OS X though
    and will be useful for on-demand launched Xwayland servers.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/include/os.h b/include/os.h
index e5f86d6..90229e6 100644
--- a/include/os.h
+++ b/include/os.h
@@ -166,9 +166,7 @@ extern _X_EXPORT void MakeClientGrabImpervious(ClientPtr /*client */ );
 
 extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client */ );
 
-#ifdef XQUARTZ
-extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
-#endif
+extern _X_EXPORT void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
 
 extern _X_EXPORT CARD32 GetTimeInMillis(void);
 extern _X_EXPORT CARD64 GetTimeInMicros(void);
diff --git a/os/connection.c b/os/connection.c
index ddf4f0a..400c542 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -1253,8 +1253,7 @@ MakeClientGrabPervious(ClientPtr client)
     }
 }
 
-#ifdef XQUARTZ
-/* Add a fd (from launchd) to our listeners */
+/* Add a fd (from launchd or similar) to our listeners */
 void
 ListenOnOpenFD(int fd, int noxauth)
 {
@@ -1276,7 +1275,7 @@ ListenOnOpenFD(int fd, int noxauth)
      */
     ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
     if (ciptr == NULL) {
-        ErrorF("Got NULL while trying to Reopen launchd port.\n");
+        ErrorF("Got NULL while trying to Reopen listen port.\n");
         return;
     }
 
@@ -1308,5 +1307,3 @@ ListenOnOpenFD(int fd, int noxauth)
     XdmcpReset();
 #endif
 }
-
-#endif
commit 797781c7bfd7a0df354fb85aa73df4560828b90b
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Mar 19 10:27:39 2014 -0700

    test: Don't add TEST_LDADD to list test
    
    The list test case is always enabled, even if Xorg is disabled.
    TEST_LDADD pulls in Xorg files which breaks linking when Xorg is disabled.
    The list test doesn't need any libraries, so just remove list_LDADD.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Cc: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/test/Makefile.am b/test/Makefile.am
index f8aa659..88fb6aa 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -30,7 +30,6 @@ endif
 xkb_LDADD=$(TEST_LDADD)
 input_LDADD=$(TEST_LDADD)
 xtest_LDADD=$(TEST_LDADD)
-list_LDADD=$(TEST_LDADD)
 misc_LDADD=$(TEST_LDADD)
 fixes_LDADD=$(TEST_LDADD)
 xfree86_LDADD=$(TEST_LDADD)
commit 4fb31e4824d46edc80bb49b4065152899faa5ac6
Merge: d18d3f6 0e531fb
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 19 06:43:14 2014 -0700

    Merge remote-tracking branch 'whot/for-keith'

commit 0e531fbb97868b9a869044fc5a4f6cb58de6751e
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Mar 12 16:31:25 2014 +1000

    xkb: add XkbLoadKeymapFromString
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/include/input.h b/include/input.h
index 93c4510..36463f2 100644
--- a/include/input.h
+++ b/include/input.h
@@ -385,6 +385,12 @@ extern _X_EXPORT Bool InitKeyboardDeviceStruct(DeviceIntPtr /*device */ ,
                                                KbdCtrlProcPtr /*controlProc */
                                                );
 
+extern _X_EXPORT Bool InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
+							 const char *keymap,
+							 int keymap_length,
+							 BellProcPtr bell_func,
+							 KbdCtrlProcPtr ctrl_func);
+
 extern int ApplyPointerMapping(DeviceIntPtr /* pDev */ ,
                                CARD8 * /* map */ ,
                                int /* len */ ,
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index c1c1561..a80e119 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -876,4 +876,8 @@ extern _X_EXPORT XkbDescPtr XkbCompileKeymap(DeviceIntPtr /* dev */ ,
                                              XkbRMLVOSet *      /* rmlvo */
     );
 
+extern _X_EXPORT XkbDescPtr XkbCompileKeymapFromString(DeviceIntPtr dev,
+						       const char *keymap,
+						       int keymap_length);
+
 #endif                          /* _XKBSRV_H_ */
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 76bf09c..1dc0e4e 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -68,6 +68,9 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define PATHSEPARATOR "/"
 #endif
 
+static unsigned
+LoadXKM(unsigned want, unsigned need, const char *keymap, XkbDescPtr *xkbRtrn);
+
 static void
 OutputDirectory(char *outdir, size_t size)
 {
@@ -255,6 +258,46 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
     return rc;
 }
 
+typedef struct {
+    const char *keymap;
+    size_t len;
+} XkbKeymapString;
+
+static void
+xkb_write_keymap_string_cb(FILE *out, void *userdata)
+{
+    XkbKeymapString *s = userdata;
+    fwrite(s->keymap, s->len, 1, out);
+}
+
+static unsigned int
+XkbDDXLoadKeymapFromString(DeviceIntPtr keybd,
+                          const char *keymap, int keymap_length,
+                          unsigned int want,
+                          unsigned int need,
+                          XkbDescPtr *xkbRtrn)
+{
+    unsigned int have;
+    char *map_name;
+    XkbKeymapString map = {
+        .keymap = keymap,
+        .len = keymap_length
+    };
+
+    *xkbRtrn = NULL;
+
+    map_name = RunXkbComp(xkb_write_keymap_string_cb, &map);
+    if (!map_name) {
+        LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
+        return 0;
+    }
+
+    have = LoadXKM(want, need, map_name, xkbRtrn);
+    free(map_name);
+
+    return have;
+}
+
 static FILE *
 XkbDDXOpenConfigFile(const char *mapName, char *fileNameRtrn, int fileNameRtrnLen)
 {
@@ -486,3 +529,32 @@ XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
 
     return KeymapOrDefaults(dev, xkb);
 }
+
+XkbDescPtr
+XkbCompileKeymapFromString(DeviceIntPtr dev,
+                           const char *keymap, int keymap_length)
+{
+    XkbDescPtr xkb;
+    unsigned int need, provided;
+
+    if (!dev || !keymap) {
+        LogMessage(X_ERROR, "XKB: No device or keymap specified\n");
+        return NULL;
+    }
+
+    /* These are the components we really really need */
+    need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask |
+           XkmKeyNamesMask | XkmVirtualModsMask;
+
+    provided =
+        XkbDDXLoadKeymapFromString(dev, keymap, keymap_length,
+                                   XkmAllIndicesMask, need, &xkb);
+    if ((need & provided) != need) {
+        if (xkb) {
+            XkbFreeKeyboard(xkb, 0, TRUE);
+            xkb = NULL;
+        }
+    }
+
+    return KeymapOrDefaults(dev, xkb);
+}
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index 33420b6..06ec46e 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -505,9 +505,10 @@ XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
     return Success;
 }
 
-_X_EXPORT Bool
-InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
-                         BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
+static Bool
+InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
+                                 const char *keymap, int keymap_length,
+                                 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
 {
     int i;
     unsigned int check;
@@ -521,8 +522,9 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
     BUG_RETURN_VAL(dev == NULL, FALSE);
     BUG_RETURN_VAL(dev->key != NULL, FALSE);
     BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE);
+    BUG_RETURN_VAL(rmlvo && keymap, FALSE);
 
-    if (!rmlvo) {
+    if (!rmlvo && !keymap) {
         rmlvo = &rmlvo_dflts;
         XkbGetRulesDflts(rmlvo);
     }
@@ -550,7 +552,7 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
     }
     dev->key->xkbInfo = xkbi;
 
-    if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
+    if (xkb_cached_map && (keymap || (rmlvo && !XkbCompareUsedRMLVO(rmlvo)))) {
         XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
         xkb_cached_map = NULL;
     }
@@ -558,7 +560,11 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
     if (xkb_cached_map)
         LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
     else {
-        xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
+        if (rmlvo)
+            xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
+        else
+            xkb_cached_map = XkbCompileKeymapFromString(dev, keymap, keymap_length);
+
         if (!xkb_cached_map) {
             ErrorF("XKB: Failed to compile keymap\n");
             goto unwind_info;
@@ -627,8 +633,10 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
 
     dev->kbdfeed->CtrlProc(dev, &dev->kbdfeed->ctrl);
 
-    XkbSetRulesDflts(rmlvo);
-    XkbSetRulesUsed(rmlvo);
+    if (rmlvo) {
+        XkbSetRulesDflts(rmlvo);
+        XkbSetRulesUsed(rmlvo);
+    }
     XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
 
     return TRUE;
@@ -647,6 +655,24 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
     return FALSE;
 }
 
+_X_EXPORT Bool
+InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
+                         BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
+{
+    return InitKeyboardDeviceStructInternal(dev, rmlvo,
+                                            NULL, 0, bell_func, ctrl_func);
+}
+
+_X_EXPORT Bool
+InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
+                                   const char *keymap, int keymap_length,
+                                   BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
+{
+    return InitKeyboardDeviceStructInternal(dev, NULL,
+                                            keymap, keymap_length,
+                                            bell_func, ctrl_func);
+}
+
 /***====================================================================***/
 
         /*
commit d18d3f6d18aa7827748f7ba14efd405b525883d0
Merge: 81a4952 6649d00
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 17:29:56 2014 -0700

    Merge remote-tracking branch 'anholt/glamor-megaseries'

commit 6649d0059e1bc136b84a9e457ae81c07521fadc0
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Mar 17 13:16:48 2014 +0900

    glamor: Move up glamor_priv->flags assignment in glamor_init()
    
    It wasn't assigned yet when it was tested for GLAMOR_NO_DRI3.
    
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index a624a7b..0f7d68b 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -313,6 +313,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     if (glamor_priv == NULL)
         return FALSE;
 
+    glamor_priv->flags = flags;
     if (flags & GLAMOR_INVERTED_Y_AXIS) {
         glamor_priv->yInverted = TRUE;
     }
@@ -487,7 +488,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_pixmap_init(screen);
     glamor_glyphs_init(screen);
 
-    glamor_priv->flags = flags;
     glamor_priv->screen = screen;
 
     return TRUE;
commit b5a61239e2fef167c229154d7919ff862503e3f3
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 14 13:10:04 2014 -0700

    glx: Make sure we get an FBConfig the root window's visual.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index eaf5654..9903cc7 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -313,6 +313,7 @@ ephyr_glamor_get_visual(void)
         GLX_GREEN_SIZE, 1,
         GLX_BLUE_SIZE, 1,
         GLX_DOUBLEBUFFER, 1,
+        GLX_VISUAL_ID, DefaultVisual(dpy, DefaultScreen(dpy)),
         None
     };
     int event_base = 0, error_base = 0, nelements;
commit 9999a660135fafe5f1fdf9452e5ca74ffb069dc2
Author: Markus Wick <markus at selfnet.de>
Date:   Thu Mar 13 11:17:39 2014 +0100

    glamor: don't reset the GLSL program
    
    We don't use fixed function rendering, so there is no need to reset
    the program at all.  This lets the driver avoid checking for state
    changes between draw calls when we rebind the same program.
    
    Improves xephyr x11perf -f8text performance by 6.03062% +/- 1.64928%
    (n=20)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 0b170dc..996611c 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -205,7 +205,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(0);
     /* The source texture is bound to a fbo, we have to flush it here. */
     glamor_put_context(glamor_priv);
     glamor_priv->state = RENDER_STATE;
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 9e07b2b..6c0b3c8 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -289,7 +289,6 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
     glUniform1i(sampler_uniform_location, 0);
     glUniform1i(glamor_priv->finish_access_revert[0], 0);
     glUniform1i(glamor_priv->finish_access_swap_rb[0], 0);
-    glUseProgram(0);
 
     glamor_priv->finish_access_revert[1] =
         glGetUniformLocation(glamor_priv->finish_access_prog[1], "revert");
@@ -301,7 +300,6 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
     glUniform1i(glamor_priv->finish_access_revert[1], 0);
     glUniform1i(sampler_uniform_location, 0);
     glUniform1i(glamor_priv->finish_access_swap_rb[1], 0);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
 }
 
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index e58b336..7461b62 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -258,7 +258,6 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
         free(vertices);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index 5d785a0..a58cef9 100644
--- a/glamor/glamor_glyphblt.c
+++ b/glamor/glamor_glyphblt.c
@@ -156,7 +156,6 @@ glamor_poly_glyph_blt_pixels(DrawablePtr drawable, GCPtr gc,
     }
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glUseProgram(0);
 
     glamor_put_context(glamor_priv);
 
@@ -328,7 +327,6 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
     glDrawArrays(GL_POINTS, 0, num_points);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glUseProgram(0);
 
     glamor_put_context(glamor_priv);
 
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 0769eae..f77d6a8 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -379,8 +379,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
 
     glamor_link_glsl_prog(screen, gradient_prog, "radial gradient");
 
-    glUseProgram(0);
-
     if (dyn_gen) {
         index = 2;
         glamor_priv->radial_max_nstops = stops_count;
@@ -592,8 +590,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
 
     glamor_link_glsl_prog(screen, gradient_prog, "linear gradient");
 
-    glUseProgram(0);
-
     if (dyn_gen) {
         index = 2;
         glamor_priv->linear_max_nstops = stops_count;
@@ -1169,7 +1165,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(0);
 
     glamor_put_context(glamor_priv);
     return dst_picture;
@@ -1191,7 +1186,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
     return NULL;
 }
@@ -1522,7 +1516,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(0);
 
     glamor_put_context(glamor_priv);
     return dst_picture;
@@ -1544,7 +1537,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
     return NULL;
 }
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 1c258a2..615faad 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -856,7 +856,6 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
 
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-    glUseProgram(0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDeleteTextures(1, &tex);
@@ -1181,7 +1180,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
     return temp_fbo;
 }
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 2496f84..c0ee22c 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1335,7 +1335,6 @@ glamor_composite_with_shader(CARD8 op,
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
     glDisable(GL_BLEND);
     DEBUGF("finish rendering.\n");
-    glUseProgram(0);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
     if (saved_source_format)
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index ba7f11f..9e115ca 100644
--- a/glamor/glamor_tile.c
+++ b/glamor/glamor_tile.c
@@ -82,7 +82,6 @@ glamor_init_tile_shader(ScreenPtr screen)
 
     glamor_priv->tile_wh =
         glGetUniformLocation(glamor_priv->tile_prog, "wh");
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
 }
 
@@ -156,7 +155,6 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
 
     glamor_priv->state = RENDER_STATE;
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 9c39740..969ab68 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -982,7 +982,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
     glDisable(GL_BLEND);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
 
  TRAPEZOID_OUT:
@@ -1359,8 +1358,6 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
 
     glamor_link_glsl_prog(screen, glamor_priv->trapezoid_prog, "trapezoid");
 
-    glUseProgram(0);
-
     glamor_put_context(glamor_priv);
 }
 
@@ -1573,7 +1570,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
     glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
     glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
     return TRUE;
 }
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index c0219b0..17745a4 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -416,7 +416,6 @@ glamor_display_textured_video(glamor_port_private *port_priv)
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    glUseProgram(0);
     glamor_put_context(glamor_priv);
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
commit aa2635b804e7d28322f62d802190bdf0bb799634
Author: Markus Wick <markus at selfnet.de>
Date:   Thu Mar 13 00:24:04 2014 +0100

    glamor: remove disabled code
    
    This block was disabled since 2011, so there is likely no need to keep it any more.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c
index b77238c..cf7197b 100644
--- a/glamor/glamor_putimage.c
+++ b/glamor/glamor_putimage.c
@@ -35,206 +35,7 @@
 void
 glamor_init_putimage_shaders(ScreenPtr screen)
 {
-#if 0
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    const char *xybitmap_vs =
-        "uniform float x_bias;\n"
-        "uniform float x_scale;\n"
-        "uniform float y_bias;\n"
-        "uniform float y_scale;\n"
-        "varying vec2 bitmap_coords;\n"
-        "void main()\n"
-        "{\n"
-        "	gl_Position = vec4((gl_Vertex.x + x_bias) * x_scale,\n"
-        "			   (gl_Vertex.y + y_bias) * y_scale,\n"
-        "			   0,\n"
-        "			   1);\n"
-        "	bitmap_coords = gl_MultiTexCoord0.xy;\n"
-        "}\n";
-    const char *xybitmap_fs =
-        "uniform vec4 fg, bg;\n"
-        "varying vec2 bitmap_coords;\n"
-        "uniform sampler2D bitmap_sampler;\n"
-        "void main()\n"
-        "{\n"
-        "	float bitmap_value = texture2D(bitmap_sampler,\n"
-        "				       bitmap_coords).x;\n"
-        "	gl_FragColor = mix(bg, fg, bitmap_value);\n"
-        "}\n";
-    GLint fs_prog, vs_prog, prog;
-    GLint sampler_uniform_location;
-
-    if (!GLEW_ARB_fragment_shader)
-        return;
-
-    prog = glCreateProgram();
-    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xybitmap_vs);
-    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xybitmap_fs);
-    glAttachShader(prog, vs_prog);
-    glAttachShader(prog, fs_prog);
-    glamor_link_glsl_prog(prog);
-
-    glUseProgram(prog);
-    sampler_uniform_location = glGetUniformLocation(prog, "bitmap_sampler");
-    glUniform1i(sampler_uniform_location, 0);
-
-    glamor_priv->put_image_xybitmap_fg_uniform_location =
-        glGetUniformLocation(prog, "fg");
-    glamor_priv->put_image_xybitmap_bg_uniform_location =
-        glGetUniformLocation(prog, "bg");
-    glamor_get_transform_uniform_locations(prog,
-                                           &glamor_priv->
-                                           put_image_xybitmap_transform);
-    glamor_priv->put_image_xybitmap_prog = prog;
-    glUseProgram(0);
-#endif
-}
-
-/* Do an XYBitmap putimage.  The bits are byte-aligned rows of bitmap
- * data (where each row starts at a bit index of left_pad), and the
- * destination gets filled with the gc's fg color where the bitmap is set
- * and the bg color where the bitmap is unset.
- *
- * Implement this by passing the bitmap right through to GL, and sampling
- * it to choose between fg and bg in the fragment shader.  The driver may
- * be exploding the bitmap up to be an 8-bit alpha texture, in which
- * case we might be better off just doing the fg/bg choosing in the CPU
- * and just draw the resulting texture to the destination.
- */
-#if 0
-
-static int
-y_flip(PixmapPtr pixmap, int y)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
-
-    if (pixmap == screen_pixmap)
-        return (pixmap->drawable.height - 1) - y;
-    else
-        return y;
-}
-
-static void
-glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
-                          int x, int y, int w, int h, int left_pad,
-                          int image_format, char *bits)
-{
-    ScreenPtr screen = drawable->pScreen;
-    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    float fg[4], bg[4];
-    GLuint tex;
-    unsigned int stride = PixmapBytePad(1, w + left_pad);
-    RegionPtr clip;
-    BoxPtr box;
-    int nbox;
-    float dest_coords[8];
-
-    const float bitmap_coords[8] = {
-        0.0, 0.0,
-        1.0, 0.0,
-        1.0, 1.0,
-        0.0, 1.0,
-    };
-    GLfloat xscale, yscale;
-    glamor_pixmap_private *pixmap_priv;
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    pixmap_priv_get_scale(pixmap_priv, &xscale, &yscale);
-
-    glamor_set_normalize_vcoords(xscale, yscale,
-                                 x, y,
-                                 x + w, y + h,
-                                 glamor_priv->yInverted, dest_coords);
-
-    glamor_fallback("glamor_put_image_xybitmap: disabled\n");
-    goto fail;
-
-    if (glamor_priv->put_image_xybitmap_prog == 0) {
-        ErrorF("no program for xybitmap putimage\n");
-        goto fail;
-    }
-
-    glamor_set_alu(gc->alu);
-    if (!glamor_set_planemask(pixmap, gc->planemask))
-        goto fail;
-
-    glUseProgram(glamor_priv->put_image_xybitmap_prog);
-
-    glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg);
-    glUniform4fv(glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg);
-    glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg);
-    glUniform4fv(glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg);
-
-    glGenTextures(1, &tex);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8);
-    glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
-                 w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits);
-    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
-
-    /* Now that we've set up our bitmap texture and the shader, shove
-     * the destination rectangle through the cliprects and run the
-     * shader on the resulting fragments.
-     */
-    glVertexPointer(2, GL_FLOAT, 0, dest_coords);
-    glEnableClientState(GL_VERTEX_ARRAY);
-    glClientActiveTexture(GL_TEXTURE0);
-    glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords);
-    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-    glEnable(GL_SCISSOR_TEST);
-    clip = fbGetCompositeClip(gc);
-    for (nbox = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nbox--; box++) {
-        int x1 = x;
-        int y1 = y;
-        int x2 = x + w;
-        int y2 = y + h;
-
-        if (x1 < box->x1)
-            x1 = box->x1;
-        if (y1 < box->y1)
-            y1 = box->y1;
-        if (x2 > box->x2)
-            x2 = box->x2;
-        if (y2 > box->y2)
-            y2 = box->y2;
-        if (x1 >= x2 || y1 >= y2)
-            continue;
-
-        glScissor(box->x1, y_flip(pixmap, box->y1),
-                  box->x2 - box->x1, box->y2 - box->y1);
-        glDrawArrays(GL_QUADS, 0, 4);
-    }
-
-    glDisable(GL_SCISSOR_TEST);
-    glamor_set_alu(GXcopy);
-    glamor_set_planemask(pixmap, ~0);
-    glDeleteTextures(1, &tex);
-    glDisableClientState(GL_VERTEX_ARRAY);
-    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-    return;
-    glamor_set_alu(GXcopy);
-    glamor_set_planemask(pixmap, ~0);
-    glamor_fallback(": to %p (%c)\n",
-                    drawable, glamor_get_drawable_location(drawable));
- fail:
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) &&
-        glamor_prepare_access_gc(gc)) {
-        fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits);
-    }
-    glamor_finish_access_gc(gc);
-    glamor_finish_access(drawable);
 }
-#endif
 
 void
 glamor_fini_putimage_shaders(ScreenPtr screen)
commit 6227f07b69b8ab3cd39cf9d257daf2a7202b4ef5
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Tue Mar 11 17:28:10 2014 -0700

    Remove duplicate assignment of repeat_type_uniform_location
    
    Flagged by cppcheck 1.64:
    [glamor/glamor_gradient.c:987] -> [glamor/glamor_gradient.c:991]:
        (performance) Variable 'repeat_type_uniform_location' is
                 reassigned a value before the old one has been used.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index baa4a03..0769eae 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -983,8 +983,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
                                                         "repeat_type");
     n_stop_uniform_location = glGetUniformLocation(gradient_prog, "n_stop");
     A_value_uniform_location = glGetUniformLocation(gradient_prog, "A_value");
-    repeat_type_uniform_location =glGetUniformLocation(gradient_prog,
-                                                       "repeat_type");
     c1_uniform_location = glGetUniformLocation(gradient_prog, "c1");
     r1_uniform_location = glGetUniformLocation(gradient_prog, "r1");
     c2_uniform_location = glGetUniformLocation(gradient_prog, "c2");
commit 1a4b24993974200e26345ea6c501d4aa093169db
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 20 15:50:03 2014 -0800

    glamor: Apply debug labels to our shaders.
    
    This will help tools like fips, apitrace, or INTEL_DEBUG=shader_time
    provide useful information about the shaders in use.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 5338d45..a624a7b 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -372,6 +372,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         }
     }
 
+    glamor_priv->has_khr_debug = glamor_gl_has_extension("GL_KHR_debug");
     glamor_priv->has_pack_invert =
         glamor_gl_has_extension("GL_MESA_pack_invert");
     glamor_priv->has_fbo_blit =
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 61025c3..9e07b2b 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -83,9 +83,10 @@ glamor_compile_glsl_prog(GLenum type, const char *source)
 }
 
 void
-glamor_link_glsl_prog(GLint prog)
+glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...)
 {
     GLint ok;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     glLinkProgram(prog);
     glGetProgramiv(prog, GL_LINK_STATUS, &ok);
@@ -100,6 +101,17 @@ glamor_link_glsl_prog(GLint prog)
         ErrorF("Failed to link: %s\n", info);
         FatalError("GLSL link failure\n");
     }
+
+    if (glamor_priv->has_khr_debug) {
+        char *label;
+        va_list va;
+
+        va_start(va, format);
+        XNFvasprintf(&label, format, va);
+        glObjectLabel(GL_PROGRAM, prog, -1, label);
+        free(label);
+        va_end(va);
+    }
 }
 
 Bool
@@ -256,13 +268,15 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
                          GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(glamor_priv->finish_access_prog[0],
                          GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]);
+    glamor_link_glsl_prog(screen, glamor_priv->finish_access_prog[0],
+                          "finish access 0");
 
     glBindAttribLocation(glamor_priv->finish_access_prog[1],
                          GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(glamor_priv->finish_access_prog[1],
                          GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]);
+    glamor_link_glsl_prog(screen, glamor_priv->finish_access_prog[1],
+                          "finish access 1");
 
     glamor_priv->finish_access_revert[0] =
         glGetUniformLocation(glamor_priv->finish_access_prog[0], "revert");
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index d91dafb..e58b336 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -165,7 +165,7 @@ glamor_init_solid_shader(ScreenPtr screen)
 
     glBindAttribLocation(glamor_priv->solid_prog,
                          GLAMOR_VERTEX_POS, "v_position");
-    glamor_link_glsl_prog(glamor_priv->solid_prog);
+    glamor_link_glsl_prog(screen, glamor_priv->solid_prog, "solid");
 
     glamor_priv->solid_color_uniform_location =
         glGetUniformLocation(glamor_priv->solid_prog, "color");
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 6a7b528..baa4a03 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -377,7 +377,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
 
-    glamor_link_glsl_prog(gradient_prog);
+    glamor_link_glsl_prog(screen, gradient_prog, "radial gradient");
 
     glUseProgram(0);
 
@@ -590,7 +590,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
 
-    glamor_link_glsl_prog(gradient_prog);
+    glamor_link_glsl_prog(screen, gradient_prog, "linear gradient");
 
     glUseProgram(0);
 
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index fed1597..bc7d3f8 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -214,6 +214,7 @@ typedef struct glamor_screen_private {
     int has_pack_invert;
     int has_fbo_blit;
     int has_buffer_storage;
+    int has_khr_debug;
     int max_fbo_size;
 
     struct xorg_list
@@ -594,7 +595,8 @@ Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
                     unsigned long fg_pixel, unsigned long bg_pixel,
                     int stipple_x, int stipple_y);
 GLint glamor_compile_glsl_prog(GLenum type, const char *source);
-void glamor_link_glsl_prog(GLint prog);
+void glamor_link_glsl_prog(ScreenPtr screen, GLint prog,
+                           const char *format, ...) _X_ATTRIBUTE_PRINTF(3,4);
 void glamor_get_color_4f_from_pixel(PixmapPtr pixmap,
                                     unsigned long fg_pixel, GLfloat *color);
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 65f3778..2496f84 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -332,7 +332,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
     glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0");
     glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1");
 
-    glamor_link_glsl_prog(prog);
+    glamor_link_glsl_prog(screen, prog, "composite");
 
     shader->prog = prog;
 
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index 7288af3..ba7f11f 100644
--- a/glamor/glamor_tile.c
+++ b/glamor/glamor_tile.c
@@ -73,7 +73,7 @@ glamor_init_tile_shader(ScreenPtr screen)
                          GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(glamor_priv->tile_prog,
                          GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(glamor_priv->tile_prog);
+    glamor_link_glsl_prog(screen, glamor_priv->tile_prog, "tile");
 
     sampler_uniform_location =
         glGetUniformLocation(glamor_priv->tile_prog, "sampler");
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 0064f2a..9c39740 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -1357,7 +1357,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
     glBindAttribLocation(glamor_priv->trapezoid_prog,
                          GLAMOR_VERTEX_RIGHT_PARAM, "v_right_param");
 
-    glamor_link_glsl_prog(glamor_priv->trapezoid_prog);
+    glamor_link_glsl_prog(screen, glamor_priv->trapezoid_prog, "trapezoid");
 
     glUseProgram(0);
 
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index fb90457..c0219b0 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -109,7 +109,7 @@ glamor_init_xv_shader(ScreenPtr screen)
                          GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(glamor_priv->xv_prog,
                          GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(glamor_priv->xv_prog);
+    glamor_link_glsl_prog(screen, glamor_priv->xv_prog, "xv");
 
     glamor_put_context(glamor_priv);
 }
commit d07d2c3c5f95fd644ef563004dfa7f3c53904168
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jan 11 21:26:01 2014 -0800

    glamor: Don't forget to unmap our PBOs before using them to upload.
    
    From the GL_ARB_vertex_buffer_object spec:
    
        After the client has specified the contents of a mapped data store,
        and before the data in that store are dereferenced by any GL commands,
        the mapping must be relinquished by calling
    
            boolean UnmapBufferARB(enum target);
    
    Our mappings were only getting reaped at PBO destroy time, after the
    upload.  If the GL implementation wasn't coherent, it would have used
    stale data to do the texture upload.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 1bbcc55..1c258a2 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -726,8 +726,10 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
     assert(pbo || bits != 0);
-    if (bits == NULL)
+    if (bits == NULL) {
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
+        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+    }
     if (non_sub)
         glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits);
     else
commit 64146e4560fdf3c3a40d023ac8e22259915b05ad
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jan 11 21:11:18 2014 -0800

    glamor: Add an assert about an invariant the upload code relies on.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index bc7be9d..1bbcc55 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -725,6 +725,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
+    assert(pbo || bits != 0);
     if (bits == NULL)
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
     if (non_sub)
commit 7eb2bafe22dcc90c2fb94d2d9cae370b683dba7c
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jan 10 15:54:25 2014 +0800

    glamor: Fix ignoring the ALU during SetSpans().
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c
index ced302a..a51e4c5 100644
--- a/glamor/glamor_setspans.c
+++ b/glamor/glamor_setspans.c
@@ -48,7 +48,11 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
         goto fail;
     }
 
-    /* XXX Shall we set alu here? */
+    if (gc->alu != GXcopy) {
+        glamor_fallback("SetSpans with non-copy ALU.\n");
+        goto fail;
+    }
+
     if (!glamor_set_planemask(dest_pixmap, gc->planemask))
         goto fail;
 
commit 923c8db7ed1adfe4689f0a36496262faca44b79d
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 9 11:36:30 2014 +0800

    glamor: Improve the performance of line fallbacks.
    
    If the lines aren't solid-filled vert/horiz solid-filled rectangles,
    we fall back.  libreoffice has some diagonal lines, and the
    performance of the fallback path was atrocious.  Just fall back to
    mi's spans instead, so that we don't do an upload/download.
    
    Improves x11perf -seg100 by 863.652% +/- 9.8968% (n=5)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c
index 697fc9e..1adf45d 100644
--- a/glamor/glamor_polylines.c
+++ b/glamor/glamor_polylines.c
@@ -51,8 +51,9 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
         /* This ends up in miSetSpans, which is accelerated as well as we
          * can hope X wide lines will be.
          */
-        goto wide_line;
+        goto fail;
     }
+
     if (gc->lineStyle != LineSolid) {
         glamor_fallback("non-solid fill line style %d\n", gc->lineStyle);
         goto fail;
@@ -104,19 +105,19 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
         && glamor_ddx_fallback_check_gc(gc))
         return FALSE;
 
-    if (gc->lineWidth == 0) {
-        if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
-            glamor_prepare_access_gc(gc)) {
-            fbPolyLine(drawable, gc, mode, n, points);
-        }
-        glamor_finish_access_gc(gc);
-        glamor_finish_access(drawable);
-    }
-    else {
- wide_line:
-        /* fb calls mi functions in the lineWidth != 0 case. */
-        fbPolyLine(drawable, gc, mode, n, points);
+    switch (gc->lineStyle) {
+    case LineSolid:
+        if (gc->lineWidth == 0)
+            miZeroLine(drawable, gc, mode, n, points);
+        else
+            miWideLine(drawable, gc, mode, n, points);
+        break;
+    case LineOnOffDash:
+    case LineDoubleDash:
+        miWideDash(drawable, gc, mode, n, points);
+        break;
     }
+
     return TRUE;
 }
 
commit b6953045566dae15437d4220e68986db7a6b4ca7
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 9 10:53:04 2014 +0800

    glamor: Improve the performance of PolyGlyphBlt.
    
    Using the same idea as the previous PushPixels code, just make points
    for each point in the glyph.  This is an advantage over the pushpixels
    fallback because we can batch the BO mappings and draw calls across
    glyphs.
    
    Improves performance of x11perf -f8text by 773.389% +/- 3.50754% (n=10).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index 0a99a95..5d785a0 100644
--- a/glamor/glamor_glyphblt.c
+++ b/glamor/glamor_glyphblt.c
@@ -27,6 +27,141 @@
  */
 
 #include "glamor_priv.h"
+#include <dixfontstr.h>
+
+static Bool
+glamor_poly_glyph_blt_pixels(DrawablePtr drawable, GCPtr gc,
+                             int x, int y, unsigned int nglyph,
+                             CharInfoPtr *ppci)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    int off_x, off_y;
+    GLfloat xscale, yscale;
+    float color[4];
+    unsigned long fg_pixel = gc->fgPixel;
+    char *vbo_offset;
+    RegionPtr clip;
+    int num_points, max_points;
+    float *points = NULL;
+
+    x += drawable->x;
+    y += drawable->y;
+
+    if (gc->fillStyle != FillSolid) {
+        glamor_fallback("gc fillstyle not solid\n");
+        return FALSE;
+    }
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        return FALSE;
+
+    glamor_get_context(glamor_priv);
+    if (!glamor_set_alu(screen, gc->alu)) {
+        if (gc->alu == GXclear)
+            fg_pixel = 0;
+        else {
+            glamor_fallback("unsupported alu %x\n", gc->alu);
+            glamor_put_context(glamor_priv);
+            return FALSE;
+        }
+    }
+
+    if (!glamor_set_planemask(pixmap, gc->planemask)) {
+        glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
+        glamor_put_context(glamor_priv);
+        return FALSE;
+    }
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
+    pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
+
+    glUseProgram(glamor_priv->solid_prog);
+
+    glamor_get_rgba_from_pixel(fg_pixel,
+                               &color[0], &color[1], &color[2], &color[3],
+                               format_for_pixmap(pixmap));
+    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+
+    clip = fbGetCompositeClip(gc);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    max_points = 500;
+    num_points = 0;
+    while (nglyph--) {
+        CharInfoPtr charinfo = *ppci++;
+        int w = GLYPHWIDTHPIXELS(charinfo);
+        int h = GLYPHHEIGHTPIXELS(charinfo);
+        uint8_t *glyphbits = FONTGLYPHBITS(NULL, charinfo);
+
+        if (w && h) {
+            int glyph_x = x + charinfo->metrics.leftSideBearing;
+            int glyph_y = y - charinfo->metrics.ascent;
+            int glyph_stride = GLYPHWIDTHBYTESPADDED(charinfo);
+            int xx, yy;
+
+            for (yy = 0; yy < h; yy++) {
+                uint8_t *glyph_row = glyphbits + glyph_stride * yy;
+                for (xx = 0; xx < w; xx++) {
+                    int pt_x_i = glyph_x + xx;
+                    int pt_y_i = glyph_y + yy;
+                    float pt_x_f, pt_y_f;
+                    if (!(glyph_row[xx / 8] & (1 << xx % 8)))
+                        continue;
+
+                    if (!RegionContainsPoint(clip, pt_x_i, pt_y_i, NULL))
+                        continue;
+
+                    if (!num_points) {
+                        points = glamor_get_vbo_space(screen,
+                                                      max_points * 2 * sizeof(float),
+                                                      &vbo_offset);
+
+                        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                                              GL_FALSE, 2 * sizeof(float),
+                                              vbo_offset);
+                    }
+
+                    pt_x_f = v_from_x_coord_x(xscale, pt_x_i + off_x + 0.5);
+                    if (glamor_priv->yInverted)
+                        pt_y_f = v_from_x_coord_y_inverted(yscale, pt_y_i + off_y + 0.5);
+                    else
+                        pt_y_f = v_from_x_coord_y(yscale, pt_y_i + off_y + 0.5);
+
+                    points[num_points * 2 + 0] = pt_x_f;
+                    points[num_points * 2 + 1] = pt_y_f;
+                    num_points++;
+
+                    if (num_points == max_points) {
+                        glamor_put_vbo_space(screen);
+                        glDrawArrays(GL_POINTS, 0, num_points);
+                        num_points = 0;
+                    }
+                }
+            }
+        }
+
+        x += charinfo->metrics.characterWidth;
+    }
+
+    if (num_points) {
+        glamor_put_vbo_space(screen);
+        glDrawArrays(GL_POINTS, 0, num_points);
+    }
+
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glUseProgram(0);
+
+    glamor_put_context(glamor_priv);
+
+    return TRUE;
+}
 
 static Bool
 _glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
@@ -64,6 +199,9 @@ _glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
                        int x, int y, unsigned int nglyph,
                        CharInfoPtr *ppci, void *pglyphBase, Bool fallback)
 {
+    if (glamor_poly_glyph_blt_pixels(pDrawable, pGC, x, y, nglyph, ppci))
+        return TRUE;
+
     if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
         && glamor_ddx_fallback_check_gc(pGC))
         return FALSE;
commit b885a639144cdadcb0dae8249a168db158770604
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Jan 5 21:54:48 2014 +0800

    glamor: Improve the performance of PushPixels by, well, pushing pixels.
    
    Otherwise, mi will fall back to GetSpans()ing the bitmap, walking the
    bitmap, computing spans to be filled, and calling FillSpans().
    
    Improves x11perf -f8text by 759.373% +/- 3.33096% (n=166)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index 6f754ce..0a99a95 100644
--- a/glamor/glamor_glyphblt.c
+++ b/glamor/glamor_glyphblt.c
@@ -91,15 +91,130 @@ glamor_poly_glyph_blt_nf(DrawablePtr pDrawable, GCPtr pGC,
 }
 
 static Bool
+glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
+                          DrawablePtr drawable, int w, int h, int x, int y)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    uint8_t *bitmap_data = bitmap->devPrivate.ptr;
+    int bitmap_stride = bitmap->devKind;
+    int off_x, off_y;
+    int yy, xx;
+    GLfloat xscale, yscale;
+    float color[4];
+    unsigned long fg_pixel = gc->fgPixel;
+    float *points, *next_point;
+    int num_points = 0;
+    char *vbo_offset;
+    RegionPtr clip;
+
+    if (w * h > MAXINT / (2 * sizeof(float)))
+        return FALSE;
+
+    if (gc->fillStyle != FillSolid) {
+        glamor_fallback("gc fillstyle not solid\n");
+        return FALSE;
+    }
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        return FALSE;
+
+    glamor_get_context(glamor_priv);
+    if (!glamor_set_alu(screen, gc->alu)) {
+        if (gc->alu == GXclear)
+            fg_pixel = 0;
+        else {
+            glamor_fallback("unsupported alu %x\n", gc->alu);
+            glamor_put_context(glamor_priv);
+            return FALSE;
+        }
+    }
+
+    if (!glamor_set_planemask(pixmap, gc->planemask)) {
+        glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
+        glamor_put_context(glamor_priv);
+        return FALSE;
+    }
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
+    pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
+
+    glUseProgram(glamor_priv->solid_prog);
+
+    glamor_get_rgba_from_pixel(fg_pixel,
+                               &color[0], &color[1], &color[2], &color[3],
+                               format_for_pixmap(pixmap));
+    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+
+    points = glamor_get_vbo_space(screen, w * h * sizeof(float) * 2,
+                                  &vbo_offset);
+    next_point = points;
+
+    clip = fbGetCompositeClip(gc);
+
+    /* Note that because fb sets miTranslate in the GC, our incoming X
+     * and Y are in screen coordinate space (same for spans, but not
+     * other operations).
+     */
+    for (yy = 0; yy < h; yy++) {
+        uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride;
+        for (xx = 0; xx < w; xx++) {
+            if (bitmap_row[xx / 8] & (1 << xx % 8) &&
+                RegionContainsPoint(clip,
+                                    x + xx,
+                                    y + yy,
+                                    NULL)) {
+                next_point[0] = v_from_x_coord_x(xscale, x + xx + off_x + 0.5);
+                if (glamor_priv->yInverted)
+                    next_point[1] = v_from_x_coord_y_inverted(yscale, y + yy + off_y + 0.5);
+                else
+                    next_point[1] = v_from_x_coord_y(yscale, y + yy + off_y + 0.5);
+
+                next_point += 2;
+                num_points++;
+            }
+        }
+    }
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, 2 * sizeof(float),
+                          vbo_offset);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    glamor_put_vbo_space(screen);
+
+    glDrawArrays(GL_POINTS, 0, num_points);
+
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glUseProgram(0);
+
+    glamor_put_context(glamor_priv);
+
+    return TRUE;
+}
+
+static Bool
 _glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
                     DrawablePtr pDrawable, int w, int h, int x, int y,
                     Bool fallback)
 {
+    glamor_pixmap_private *pixmap_priv;
+
     if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
         && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable)
         && glamor_ddx_fallback_check_gc(pGC))
         return FALSE;
 
+    pixmap_priv = glamor_get_pixmap_private(pBitmap);
+    if (pixmap_priv->type == GLAMOR_MEMORY) {
+        if (glamor_push_pixels_points(pGC, pBitmap, pDrawable, w, h, x, y))
+            return TRUE;
+    }
+
     miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
     return TRUE;
 }
commit ab68982dcc53d29d5e3c5ea092bd91dab09e54c9
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jan 11 00:06:21 2014 +0800

    glamor: Add missing prepares on the GC during fb fallbacks.
    
    We had regressions in CopyPlane reported by xts5, because we were
    (successfully!) dereferencing the null pixmap->devPrivate.ptr for a
    tile or stipple without having done a prepare.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index ae3264d..0b170dc 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -571,10 +571,12 @@ _glamor_copy_n_to_n(DrawablePtr src,
                     glamor_get_drawable_location(dst));
 
     if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
+        glamor_prepare_access(src, GLAMOR_ACCESS_RO) &&
+        glamor_prepare_access_gc(gc)) {
         fbCopyNtoN(src, dst, gc, box, nbox,
                    dx, dy, reverse, upsidedown, bitplane, closure);
     }
+    glamor_finish_access_gc(gc);
     glamor_finish_access(src);
     glamor_finish_access(dst);
     ok = TRUE;
diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c
index 50e9cf3..2bd2de3 100644
--- a/glamor/glamor_copyplane.c
+++ b/glamor/glamor_copyplane.c
@@ -39,10 +39,12 @@ _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
         goto fail;
 
     if (glamor_prepare_access(pDst, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO)) {
+        glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO) &&
+        glamor_prepare_access_gc(pGC)) {
         *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
                                dstx, dsty, bitPlane);
     }
+    glamor_finish_access_gc(pGC);
     glamor_finish_access(pSrc);
     glamor_finish_access(pDst);
     return TRUE;
diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c
index a4f97cd..b77238c 100644
--- a/glamor/glamor_putimage.c
+++ b/glamor/glamor_putimage.c
@@ -227,9 +227,11 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
     glamor_fallback(": to %p (%c)\n",
                     drawable, glamor_get_drawable_location(drawable));
  fail:
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) &&
+        glamor_prepare_access_gc(gc)) {
         fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits);
     }
+    glamor_finish_access_gc(gc);
     glamor_finish_access(drawable);
 }
 #endif
diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c
index 664f8ac..ced302a 100644
--- a/glamor/glamor_setspans.c
+++ b/glamor/glamor_setspans.c
@@ -86,9 +86,11 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
 
     glamor_fallback("to %p (%c)\n",
                     drawable, glamor_get_drawable_location(drawable));
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc)) {
         fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted);
     }
+    glamor_finish_access_gc(gc);
     glamor_finish_access(drawable);
     ret = TRUE;
 
commit 93f1824a0b19346f0e1759bedfa9cf10772067af
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jan 11 00:00:00 2014 +0800

    glamor: Rely on nested mappings to handle src==dst and !prepare bugs.
    
    Now that the core deals with that for us, we can avoid all this extra
    carefulness.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_addtraps.c b/glamor/glamor_addtraps.c
index 655d87e..fdc0f42 100644
--- a/glamor/glamor_addtraps.c
+++ b/glamor/glamor_addtraps.c
@@ -40,8 +40,8 @@ _glamor_add_traps(PicturePtr pPicture,
 
     if (glamor_prepare_access_picture(pPicture, GLAMOR_ACCESS_RW)) {
         fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
-        glamor_finish_access_picture(pPicture, GLAMOR_ACCESS_RW);
     }
+    glamor_finish_access_picture(pPicture);
 
     return TRUE;
 }
diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index d03f708..ae3264d 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -570,15 +570,13 @@ _glamor_copy_n_to_n(DrawablePtr src,
                     glamor_get_drawable_location(src),
                     glamor_get_drawable_location(dst));
 
-    if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) {
-        if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
-            fbCopyNtoN(src, dst, gc, box, nbox,
-                       dx, dy, reverse, upsidedown, bitplane, closure);
-            if (dst != src)
-                glamor_finish_access(src, GLAMOR_ACCESS_RO);
-        }
-        glamor_finish_access(dst, GLAMOR_ACCESS_RW);
+    if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
+        fbCopyNtoN(src, dst, gc, box, nbox,
+                   dx, dy, reverse, upsidedown, bitplane, closure);
     }
+    glamor_finish_access(src);
+    glamor_finish_access(dst);
     ok = TRUE;
 
  done:
diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c
index c42d33e..50e9cf3 100644
--- a/glamor/glamor_copyplane.c
+++ b/glamor/glamor_copyplane.c
@@ -38,12 +38,13 @@ _glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
         && glamor_ddx_fallback_check_pixmap(pDst))
         goto fail;
 
-    glamor_prepare_access(pDst, GLAMOR_ACCESS_RW);
-    glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO);
-    *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
-                           dstx, dsty, bitPlane);
-    glamor_finish_access(pSrc, GLAMOR_ACCESS_RO);
-    glamor_finish_access(pDst, GLAMOR_ACCESS_RW);
+    if (glamor_prepare_access(pDst, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO)) {
+        *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
+                               dstx, dsty, bitPlane);
+    }
+    glamor_finish_access(pSrc);
+    glamor_finish_access(pDst);
     return TRUE;
 
  fail:
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index a6a6039..61025c3 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -304,7 +304,7 @@ glamor_fini_finish_access_shaders(ScreenPtr screen)
 }
 
 void
-glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
+glamor_finish_access(DrawablePtr drawable)
 {
     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
@@ -370,7 +370,7 @@ glamor_prepare_access_gc(GCPtr gc)
         if (!glamor_prepare_access(&gc->tile.pixmap->drawable,
                                    GLAMOR_ACCESS_RO)) {
             if (gc->stipple)
-                glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO);
+                glamor_finish_access(&gc->stipple->drawable);
             return FALSE;
         }
     }
@@ -384,9 +384,9 @@ void
 glamor_finish_access_gc(GCPtr gc)
 {
     if (gc->fillStyle == FillTiled)
-        glamor_finish_access(&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RO);
+        glamor_finish_access(&gc->tile.pixmap->drawable);
     if (gc->stipple)
-        glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO);
+        glamor_finish_access(&gc->stipple->drawable);
 }
 
 Bool
@@ -460,7 +460,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
                     (&old_tile->drawable, GLAMOR_ACCESS_RO)) {
                     new_tile =
                         fb24_32ReformatTile(old_tile, drawable->bitsPerPixel);
-                    glamor_finish_access(&old_tile->drawable, GLAMOR_ACCESS_RO);
+                    glamor_finish_access(&old_tile->drawable);
                 }
             }
             if (new_tile) {
@@ -483,8 +483,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
                 if (glamor_prepare_access
                     (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW)) {
                     fbPadPixmap(gc->tile.pixmap);
-                    glamor_finish_access
-                        (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW);
+                    glamor_finish_access(&gc->tile.pixmap->drawable);
                 }
             }
         }
@@ -500,7 +499,7 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
          */
         if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) {
             fbValidateGC(gc, changes, drawable);
-            glamor_finish_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW);
+            glamor_finish_access(&gc->stipple->drawable);
         }
     }
     else {
@@ -544,7 +543,7 @@ glamor_bitmap_to_region(PixmapPtr pixmap)
     if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO))
         return NULL;
     ret = fbPixmapToRegion(pixmap);
-    glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO);
+    glamor_finish_access(&pixmap->drawable);
     return ret;
 }
 
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index a3f0f29..d91dafb 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -112,13 +112,12 @@ glamor_fill(DrawablePtr drawable,
         x = 0;
         y = 0;
     }
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
-        if (glamor_prepare_access_gc(gc)) {
-            fbFill(drawable, gc, x, y, width, height);
-            glamor_finish_access_gc(gc);
-        }
-        glamor_finish_access(drawable, GLAMOR_ACCESS_RW);
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc)) {
+        fbFill(drawable, gc, x, y, width, height);
     }
+    glamor_finish_access_gc(gc);
+    glamor_finish_access(drawable);
 
     if (sub_pixmap != NULL) {
         if (gc->fillStyle != FillSolid) {
diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c
index 7261d28..8cbd79f 100644
--- a/glamor/glamor_fillspans.c
+++ b/glamor/glamor_fillspans.c
@@ -79,13 +79,12 @@ _glamor_fill_spans(DrawablePtr drawable,
     }
     glamor_fallback("to %p (%c)\n", drawable,
                     glamor_get_drawable_location(drawable));
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
-        if (glamor_prepare_access_gc(gc)) {
-            fbFillSpans(drawable, gc, n, points, widths, sorted);
-            glamor_finish_access_gc(gc);
-        }
-        glamor_finish_access(drawable, GLAMOR_ACCESS_RW);
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc)) {
+        fbFillSpans(drawable, gc, n, points, widths, sorted);
     }
+    glamor_finish_access_gc(gc);
+    glamor_finish_access(drawable);
     ret = TRUE;
 
  done:
diff --git a/glamor/glamor_getspans.c b/glamor/glamor_getspans.c
index ff58725..42df87f 100644
--- a/glamor/glamor_getspans.c
+++ b/glamor/glamor_getspans.c
@@ -69,8 +69,8 @@ _glamor_get_spans(DrawablePtr drawable,
     ret = TRUE;
     if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) {
         fbGetSpans(drawable, wmax, points, widths, count, dst);
-        glamor_finish_access(drawable, GLAMOR_ACCESS_RO);
     }
+    glamor_finish_access(drawable);
  done:
     return ret;
 }
diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c
index 8bbe2e9..5fdc5f9 100644
--- a/glamor/glamor_picture.c
+++ b/glamor/glamor_picture.c
@@ -55,12 +55,12 @@ glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
 }
 
 void
-glamor_finish_access_picture(PicturePtr picture, glamor_access_t access)
+glamor_finish_access_picture(PicturePtr picture)
 {
     if (!picture || !picture->pDrawable)
         return;
 
-    glamor_finish_access(picture->pDrawable, access);
+    glamor_finish_access(picture->pDrawable);
 }
 
 /* 
diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c
index a25fc4e..1e361a4 100644
--- a/glamor/glamor_polyfillrect.c
+++ b/glamor/glamor_polyfillrect.c
@@ -96,13 +96,12 @@ _glamor_poly_fill_rect(DrawablePtr drawable,
 
     glamor_fallback(" to %p (%c)\n",
                     drawable, glamor_get_drawable_location(drawable));
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
-        if (glamor_prepare_access_gc(gc)) {
-            fbPolyFillRect(drawable, gc, nrect, prect);
-            glamor_finish_access_gc(gc);
-        }
-        glamor_finish_access(drawable, GLAMOR_ACCESS_RW);
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc)) {
+        fbPolyFillRect(drawable, gc, nrect, prect);
     }
+    glamor_finish_access_gc(gc);
+    glamor_finish_access(drawable);
     ret = TRUE;
 
  done:
diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c
index b941617..697fc9e 100644
--- a/glamor/glamor_polylines.c
+++ b/glamor/glamor_polylines.c
@@ -105,13 +105,12 @@ _glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
         return FALSE;
 
     if (gc->lineWidth == 0) {
-        if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
-            if (glamor_prepare_access_gc(gc)) {
-                fbPolyLine(drawable, gc, mode, n, points);
-                glamor_finish_access_gc(gc);
-            }
-            glamor_finish_access(drawable, GLAMOR_ACCESS_RW);
+        if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+            glamor_prepare_access_gc(gc)) {
+            fbPolyLine(drawable, gc, mode, n, points);
         }
+        glamor_finish_access_gc(gc);
+        glamor_finish_access(drawable);
     }
     else {
  wide_line:
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 776de06..fed1597 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -578,7 +578,7 @@ void glamor_copy_window(WindowPtr win, DDXPointRec old_origin,
 
 /* glamor_core.c */
 Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access);
-void glamor_finish_access(DrawablePtr drawable, glamor_access_t access);
+void glamor_finish_access(DrawablePtr drawable);
 Bool glamor_prepare_access_window(WindowPtr window);
 void glamor_finish_access_window(WindowPtr window);
 Bool glamor_prepare_access_gc(GCPtr gc);
@@ -904,7 +904,7 @@ void glamor_set_window_pixmap(WindowPtr pWindow, PixmapPtr pPixmap);
 
 Bool glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access);
 
-void glamor_finish_access_picture(PicturePtr picture, glamor_access_t access);
+void glamor_finish_access_picture(PicturePtr picture);
 
 void glamor_destroy_picture(PicturePtr picture);
 
diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c
index 702e89f..a4f97cd 100644
--- a/glamor/glamor_putimage.c
+++ b/glamor/glamor_putimage.c
@@ -229,8 +229,8 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
  fail:
     if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
         fbPutImage(drawable, gc, 1, x, y, w, h, left_pad, XYBitmap, bits);
-        glamor_finish_access(drawable, GLAMOR_ACCESS_RW);
     }
+    glamor_finish_access(drawable);
 }
 #endif
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index f93aac1..65f3778 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1784,22 +1784,17 @@ _glamor_composite(CARD8 op,
     if (mask && mask->pDrawable && !mask->transform)
         GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
 
-    if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW)) {
-        if (source_pixmap == dest_pixmap || glamor_prepare_access_picture
-            (source, GLAMOR_ACCESS_RO)) {
-            if (!mask || glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) {
-                fbComposite(op,
-                            source, mask, dest,
-                            x_source, y_source,
-                            x_mask, y_mask, x_dest, y_dest, width, height);
-                if (mask)
-                    glamor_finish_access_picture(mask, GLAMOR_ACCESS_RO);
-            }
-            if (source_pixmap != dest_pixmap)
-                glamor_finish_access_picture(source, GLAMOR_ACCESS_RO);
-        }
-        glamor_finish_access_picture(dest, GLAMOR_ACCESS_RW);
-    }
+    if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO) &&
+        glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) {
+        fbComposite(op,
+                    source, mask, dest,
+                    x_source, y_source,
+                    x_mask, y_mask, x_dest, y_dest, width, height);
+    }
+    glamor_finish_access_picture(mask);
+    glamor_finish_access_picture(source);
+    glamor_finish_access_picture(dest);
 
 #define PUT_SUB_PICTURE(p, access)		do {				\
 	if (sub_ ##p ##_pixmap != NULL) {					\
diff --git a/glamor/glamor_setspans.c b/glamor/glamor_setspans.c
index 22fe88c..664f8ac 100644
--- a/glamor/glamor_setspans.c
+++ b/glamor/glamor_setspans.c
@@ -88,8 +88,8 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
                     drawable, glamor_get_drawable_location(drawable));
     if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
         fbSetSpans(drawable, gc, src, points, widths, numPoints, sorted);
-        glamor_finish_access(drawable, GLAMOR_ACCESS_RW);
     }
+    glamor_finish_access(drawable);
     ret = TRUE;
 
  done:
diff --git a/glamor/glamor_triangles.c b/glamor/glamor_triangles.c
index 693eef1..b89cb2d 100644
--- a/glamor/glamor_triangles.c
+++ b/glamor/glamor_triangles.c
@@ -41,16 +41,13 @@ _glamor_triangles(CARD8 op,
             || glamor_ddx_fallback_check_pixmap(pSrc->pDrawable)))
         return FALSE;
 
-    if (glamor_prepare_access_picture(pDst, GLAMOR_ACCESS_RW)) {
-        if (glamor_prepare_access_picture(pSrc, GLAMOR_ACCESS_RO)) {
-
-            fbTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris);
-
-            glamor_finish_access_picture(pSrc, GLAMOR_ACCESS_RO);
-        }
-
-        glamor_finish_access_picture(pDst, GLAMOR_ACCESS_RW);
+    if (glamor_prepare_access_picture(pDst, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_picture(pSrc, GLAMOR_ACCESS_RO)) {
+        fbTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntris, tris);
     }
+    glamor_finish_access_picture(pSrc);
+    glamor_finish_access_picture(pDst);
+
     return TRUE;
 }
 
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index f9550b7..53b7d9b 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1177,7 +1177,7 @@ glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int h)
     default:
         ErrorF("dump depth %d, not implemented.\n", pixmap->drawable.depth);
     }
-    glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO);
+    glamor_finish_access(&pixmap->drawable);
 }
 
 static inline void
@@ -1318,13 +1318,12 @@ glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
 {
     assert(pixmap1->drawable.depth == pixmap2->drawable.depth);
 
-    glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO);
-    glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO);
-
-    _glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs);
-
-    glamor_finish_access(&pixmap1->drawable, GLAMOR_ACCESS_RO);
-    glamor_finish_access(&pixmap2->drawable, GLAMOR_ACCESS_RO);
+    if (glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO) &&
+        glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO)) {
+        _glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs);
+    }
+    glamor_finish_access(&pixmap1->drawable);
+    glamor_finish_access(&pixmap2->drawable);
 }
 
 /* This function is used to compare two pictures.
@@ -1432,9 +1431,6 @@ glamor_compare_pictures(ScreenPtr screen,
         return;
     }
 
-    glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO);
-    glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO);
-
     if ((fst_type == SourcePictTypeLinear) ||
         (fst_type == SourcePictTypeRadial) ||
         (fst_type == SourcePictTypeConical) ||
@@ -1444,12 +1440,15 @@ glamor_compare_pictures(ScreenPtr screen,
         x_source = y_source = 0;
     }
 
-    _glamor_compare_pixmaps(fst_pixmap, snd_pixmap,
-                            x_source, y_source,
-                            width, height, fst_picture->format, all, diffs);
-
-    glamor_finish_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO);
-    glamor_finish_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO);
+    if (glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO) &&
+        glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO)) {
+        _glamor_compare_pixmaps(fst_pixmap, snd_pixmap,
+                                x_source, y_source,
+                                width, height, fst_picture->format,
+                                all, diffs);
+    }
+    glamor_finish_access(&fst_pixmap->drawable);
+    glamor_finish_access(&snd_pixmap->drawable);
 
     if (fst_generated)
         glamor_destroy_picture(fst_picture);
commit 4c9a20072552c52b3763bd73e7a7e9b9cb8b4993
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jan 10 23:43:09 2014 +0800

    glamor: Allow nested mapping of pixmaps.
    
    The common pattern is to do nested if statements making calls to
    prepare_access() and then pop those mappings back off in each set of
    braces.  Some cases checked for src == dst to avoid leaking mappings,
    but others didn't.  Others didn't even do the nested mappings, so a
    failure in the outer map would result in trying to umap the inner and
    failing.
    
    By allowing nested mappings, we can fix both problems by not requiring
    the care from the caller, plus we can allow a simpler nesting of all
    the prepares in one if statement.
    
    v2: Add a comment about nested unmap behavior, and just reuse the
        glamor_access_t enum.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 6b10e97..a6a6039 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -106,6 +106,19 @@ Bool
 glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
 {
     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    if (pixmap->devPrivate.ptr) {
+        /* Already mapped, nothing needs to be done.  Note that we
+         * aren't allowing promotion from RO to RW, because it would
+         * require re-mapping the PBO.
+         */
+        assert(!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) ||
+               access == GLAMOR_ACCESS_RO ||
+               pixmap_priv->base.mapped_for_write);
+        return TRUE;
+    }
+    pixmap_priv->base.map_access = access;
 
     return glamor_download_pixmap_to_cpu(pixmap, access);
 }
@@ -301,7 +314,15 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv))
         return;
 
-    if (access_mode != GLAMOR_ACCESS_RO) {
+    /* If we are doing a series of unmaps from a nested map, we're
+     * done.  None of the callers do any rendering to maps after
+     * starting an unmap sequence, so we don't need to delay until the
+     * last nested unmap.
+     */
+    if (!pixmap->devPrivate.ptr)
+        return;
+
+    if (pixmap_priv->base.map_access == GLAMOR_ACCESS_RW) {
         glamor_restore_pixmap_to_texture(pixmap);
     }
 
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 3cc0d24..776de06 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -410,6 +410,12 @@ typedef struct glamor_pixmap_clipped_regions {
 typedef struct glamor_pixmap_private_base {
     glamor_pixmap_type_t type;
     enum glamor_fbo_state gl_fbo;
+    /**
+     * If devPrivate.ptr is non-NULL (meaning we're within
+     * glamor_prepare_access), determies whether we should re-upload
+     * that data on glamor_finish_access().
+     */
+    glamor_access_t map_access;
     unsigned char is_picture:1;
     unsigned char gl_tex:1;
     glamor_pixmap_fbo *fbo;
commit d86eacedab443f172baccf544d17e09090f71f3c
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jan 10 23:39:02 2014 +0800

    glamor: Drop unused GLAMOR_ACCESS_WO.
    
    Nothing was using it, and it was going to complicate the
    glamor_prepare_access bugfixing I'm going to do next.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 6ecabb5..bc7be9d 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -1216,8 +1216,6 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         gl_access = GL_READ_ONLY;
         gl_usage = GL_STREAM_READ;
         break;
-    case GLAMOR_ACCESS_WO:
-        return bits;
     case GLAMOR_ACCESS_RW:
         gl_access = GL_READ_WRITE;
         gl_usage = GL_DYNAMIC_DRAW;
@@ -1472,8 +1470,7 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
 
     stride = pixmap->devKind;
 
-    if (access == GLAMOR_ACCESS_WO
-        || glamor_priv->gl_flavor == GLAMOR_GL_ES2
+    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
         || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)
         || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
         data = malloc(stride * pixmap->drawable.height);
@@ -1603,12 +1600,6 @@ glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h,
         return NULL;
     w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
     h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
-    if (access == GLAMOR_ACCESS_WO) {
-        sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
-                                          pixmap->drawable.depth,
-                                          GLAMOR_CREATE_PIXMAP_CPU);
-        return sub_pixmap;
-    }
 
     glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
     pixmap_priv = glamor_get_pixmap_private(pixmap);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 0c69990..3cc0d24 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -288,7 +288,6 @@ typedef struct glamor_screen_private {
 typedef enum glamor_access {
     GLAMOR_ACCESS_RO,
     GLAMOR_ACCESS_RW,
-    GLAMOR_ACCESS_WO,
 } glamor_access_t;
 
 enum glamor_fbo_state {
commit c36b903f240664f7222cfefc480e60fca936de6a
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 13 10:09:08 2014 -0700

    glamor: Drop stale comment.
    
    The old Xephyr codebase was using the GL window system framebuffer for
    the screen pixmap, but that meant you couldn't texture from it to do
    operations sourcing from the screen, so in the version that landed I
    instead had the screen just be a plain texture.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 8569ae2..f93aac1 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -962,10 +962,6 @@ glamor_composite_choose_shader(CARD8 op,
             glamor_fallback("source == dest\n");
         }
         if (source_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
-            /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex
-             * equal to zero when the pixmap is screen pixmap. Then we may
-             * refer the tex zero directly latter in the composition.
-             * It seems that it works fine, but it may have potential problem*/
 #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
             source_status = GLAMOR_UPLOAD_PENDING;
 #else
commit f7cd1189d068471373f51d932c558f8151182d58
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jan 10 22:42:02 2014 +0800

    glamor: Replace some goofy enum-likes with a real enum.
    
    This unpacks the bitfield into an int size, but my experience has been
    that packing bitfields doesn't matter for performance.
    
    v2: Convert more comparisons against numbers or implicit bool
        comparisons to comparisons against the enum names, and fix up some
        comments.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index d6bcacd..d03f708 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -137,7 +137,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
     src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
     dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
 
-    if (!src_pixmap_priv->base.gl_fbo) {
+    if (src_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
 #ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
         glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
         return FALSE;
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 5883809..6b10e97 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -42,7 +42,8 @@ glamor_get_drawable_location(const DrawablePtr drawable)
     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(drawable->pScreen);
-    if (pixmap_priv == NULL || pixmap_priv->base.gl_fbo == 0)
+    if (pixmap_priv == NULL ||
+        pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED)
         return 'm';
     if (pixmap_priv->base.fbo->fb == glamor_priv->screen_fbo)
         return 's';
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index 281cf83..640b6fd 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -505,7 +505,7 @@ glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo)
     case GLAMOR_TEXTURE_LARGE:
     case GLAMOR_TEXTURE_ONLY:
     case GLAMOR_TEXTURE_DRM:
-        pixmap_priv->base.gl_fbo = 1;
+        pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL;
         if (fbo->tex != 0)
             pixmap_priv->base.gl_tex = 1;
         else {
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 119e4d9..6ecabb5 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -886,7 +886,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
     pixmap_priv = glamor_get_pixmap_private(pixmap);
     glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
 
-    if (pixmap_priv->base.gl_fbo)
+    if (pixmap_priv->base.gl_fbo != GLAMOR_FBO_UNATTACHED)
         return 0;
 
     if (pixmap_priv->base.fbo
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 4dc2c75..0c69990 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -291,8 +291,21 @@ typedef enum glamor_access {
     GLAMOR_ACCESS_WO,
 } glamor_access_t;
 
-#define GLAMOR_FBO_NORMAL     1
-#define GLAMOR_FBO_DOWNLOADED 2
+enum glamor_fbo_state {
+    /** There is no storage attached to the pixmap. */
+    GLAMOR_FBO_UNATTACHED,
+    /**
+     * The pixmap has FBO storage attached, but devPrivate.ptr doesn't
+     * point at anything.
+     */
+    GLAMOR_FBO_NORMAL,
+    /**
+     * The FBO is present and can be accessed as a linear memory
+     * mapping through devPrivate.ptr.
+     */
+    GLAMOR_FBO_DOWNLOADED,
+};
+
 /* glamor_pixmap_fbo:
  * @list:    to be used to link to the cache pool list.
  * @expire:  when push to cache pool list, set a expire count.
@@ -324,12 +337,6 @@ typedef struct glamor_pixmap_fbo {
 
 /*
  * glamor_pixmap_private - glamor pixmap's private structure.
- * @gl_fbo:
- * 	0 		  	- The pixmap doesn't has a fbo attached to it.
- * 	GLAMOR_FBO_NORMAL 	- The pixmap has a fbo and can be accessed normally.
- * 	GLAMOR_FBO_DOWNLOADED 	- The pixmap has a fbo and already downloaded to
- * 				  CPU, so it can only be treated as a in-memory pixmap
- * 				  if this bit is set.
  * @gl_tex:  The pixmap is in a gl texture originally.
  * @is_picture: The drawable is attached to a picture.
  * @pict_format: the corresponding picture's format.
@@ -403,7 +410,7 @@ typedef struct glamor_pixmap_clipped_regions {
 
 typedef struct glamor_pixmap_private_base {
     glamor_pixmap_type_t type;
-    unsigned char gl_fbo:2;
+    enum glamor_fbo_state gl_fbo;
     unsigned char is_picture:1;
     unsigned char gl_tex:1;
     glamor_pixmap_fbo *fbo;
@@ -777,7 +784,7 @@ glamor_put_vbo_space(ScreenPtr screen);
  * One copy of current pixmap's texture will be put into
  * the pixmap->devPrivate.ptr. Will use pbo to map to 
  * the pointer if possible.
- * The pixmap must be a gl texture pixmap. gl_fbo and
+ * The pixmap must be a gl texture pixmap. gl_fbo must be GLAMOR_FBO_NORMAL and
  * gl_tex must be 1. Used by glamor_prepare_access.
  *
  */
@@ -792,9 +799,8 @@ void *glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w,
  * glamor_download_pixmap_to_cpu to its original 
  * gl texture. Used by glamor_finish_access. 
  *
- * The pixmap must be
- * in texture originally. In other word, the gl_fbo
- * must be 1.
+ * The pixmap must originally be a texture -- gl_fbo must be
+ * GLAMOR_FBO_NORMAL.
  **/
 void glamor_restore_pixmap_to_texture(PixmapPtr pixmap);
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 086526d..8569ae2 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -961,7 +961,7 @@ glamor_composite_choose_shader(CARD8 op,
              * Does it need special handle? */
             glamor_fallback("source == dest\n");
         }
-        if (source_pixmap_priv->base.gl_fbo == 0) {
+        if (source_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
             /* XXX in Xephyr, we may have gl_fbo equal to 1 but gl_tex
              * equal to zero when the pixmap is screen pixmap. Then we may
              * refer the tex zero directly latter in the composition.
@@ -982,7 +982,7 @@ glamor_composite_choose_shader(CARD8 op,
             glamor_fallback("mask == dest\n");
             goto fail;
         }
-        if (mask_pixmap_priv->base.gl_fbo == 0) {
+        if (mask_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
 #ifdef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
             mask_status = GLAMOR_UPLOAD_PENDING;
 #else
commit 575e3e1bf08c418430da86228d2774e8fda4b8c0
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 07:22:47 2014 +0800

    glamor: Fix up doxygen for glamor_fill.c.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index f8b39a5..a3f0f29 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -27,10 +27,14 @@
 
 #include "glamor_priv.h"
 
-/** @file glamor_fillspans.c
+/** @file glamor_fill.c
  *
  * GC fill implementation, based loosely on fb_fill.c
  */
+
+/**
+ * Fills the given rectangle of a drawable with the GC's fill style.
+ */
 Bool
 glamor_fill(DrawablePtr drawable,
             GCPtr gc, int x, int y, int width, int height, Bool fallback)
@@ -261,6 +265,12 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     glamor_priv->render_idle_cnt = 0;
 }
 
+/**
+ * Fills the given rectangles of pixmap with an X pixel value.
+ *
+ * This is a helper used by other code after clipping and translation
+ * of coordinates to a glamor backing pixmap.
+ */
 Bool
 glamor_solid_boxes(PixmapPtr pixmap,
                    BoxPtr box, int nbox, unsigned long fg_pixel)
@@ -308,6 +318,12 @@ glamor_solid_boxes(PixmapPtr pixmap,
     return TRUE;
 }
 
+/**
+ * Fills a rectangle of a pixmap with an X pixel value.
+ *
+ * This is a helper used by other glamor code mostly for clearing of
+ * buffers to 0.
+ */
 Bool
 glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
              unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
commit 53996e252e51c8053537f485616a078cb7b0f738
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 07:05:02 2014 +0800

    glamor: Rename more solid fill variables to clean up the code.
    
    Now the error path of allocation is more obvious: We leave things in
    the a-few-boxes-at-a-time stack memory state.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index 12b8c37..f8b39a5 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -187,9 +187,9 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
     GLfloat xscale, yscale;
-    float vertices[32];
-    float *pvertices = vertices;
-    int valid_nbox = ARRAY_SIZE(vertices) / (4 * 2);
+    float stack_vertices[32];
+    float *vertices = stack_vertices;
+    int valid_nbox = ARRAY_SIZE(stack_vertices) / (4 * 2);
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
@@ -201,19 +201,17 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
 
     if (nbox > valid_nbox) {
-        int allocated_box;
+        int allocated_nbox;
+        float *new_vertices;
 
-        if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6) {
-            allocated_box = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
-        }
+        if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6)
+            allocated_nbox = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
         else
-            allocated_box = nbox;
-        pvertices = malloc(allocated_box * 4 * 2 * sizeof(float));
-        if (pvertices)
-            valid_nbox = allocated_box;
-        else {
-            pvertices = vertices;
-            valid_nbox = ARRAY_SIZE(vertices) / (4 * 2);
+            allocated_nbox = nbox;
+        new_vertices = malloc(allocated_nbox * 4 * 2 * sizeof(float));
+        if (new_vertices) {
+            vertices = new_vertices;
+            valid_nbox = allocated_nbox;
         }
     }
 
@@ -221,14 +219,14 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                          GL_FALSE, 2 * sizeof(float), pvertices);
+                          GL_FALSE, 2 * sizeof(float), vertices);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     while (nbox) {
         int box_cnt, i;
         float *next_box;
 
-        next_box = pvertices;
+        next_box = vertices;
         box_cnt = nbox > valid_nbox ? valid_nbox : nbox;
         for (i = 0; i < box_cnt; i++) {
             glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
@@ -253,8 +251,8 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
         box += box_cnt;
     }
 
-    if (pvertices != vertices)
-        free(pvertices);
+    if (vertices != stack_vertices)
+        free(vertices);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glUseProgram(0);
commit ec3ab2f67baa00326a4964ed2047e8a137915578
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 07:01:17 2014 +0800

    glamor: Rename a variable to be more descriptive.
    
    The "valid_" prefix was used above to describe our allocation that
    gets reused multiple times, which is totally unrelated.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index d5843b7..12b8c37 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -226,17 +226,17 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     while (nbox) {
         int box_cnt, i;
-        float *valid_vertices;
+        float *next_box;
 
-        valid_vertices = pvertices;
+        next_box = pvertices;
         box_cnt = nbox > valid_nbox ? valid_nbox : nbox;
         for (i = 0; i < box_cnt; i++) {
             glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
                                          box[i].x1, box[i].y1,
                                          box[i].x2, box[i].y2,
                                          glamor_priv->yInverted,
-                                         valid_vertices);
-            valid_vertices += 4 * 2;
+                                         next_box);
+            next_box += 4 * 2;
         }
         if (box_cnt == 1)
             glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
commit 01e30d2043f5df104947908f14a377dc77896a98
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 06:55:15 2014 +0800

    glamor: Fix some integer overflow errors.
    
    Imagine a nbox that was (UINT_MAX + small number) / (4 * 2 *
    sizeof(float)).  We'd malloc a few bytes after the integer overflow,
    but glamor_set_normalize_vcoords would write over gigabytes of heap.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index aaa7783..d5843b7 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -200,10 +200,10 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
 
-    if (nbox * 4 * 2 > ARRAY_SIZE(vertices)) {
+    if (nbox > valid_nbox) {
         int allocated_box;
 
-        if (nbox * 6 > GLAMOR_COMPOSITE_VBO_VERT_CNT) {
+        if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6) {
             allocated_box = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
         }
         else
commit 20bcda977755559294c3a951f80af2ec861595fc
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 06:53:46 2014 +0800

    glamor: Drop bogus _X_UNLIKELY.
    
    nbox > 4 is actually quite common for spans handling.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index 75c952c..aaa7783 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -200,7 +200,7 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
 
-    if (_X_UNLIKELY(nbox * 4 * 2 > ARRAY_SIZE(vertices))) {
+    if (nbox * 4 * 2 > ARRAY_SIZE(vertices)) {
         int allocated_box;
 
         if (nbox * 6 > GLAMOR_COMPOSITE_VBO_VERT_CNT) {
commit ad3dd80720676dcdc11ab5db63ccbed7c9509d7e
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 06:52:32 2014 +0800

    glamor: Fix stack overflow in glamor_solid vertex handling.
    
    ARRAY_SIZE(vertices) is 32 (floating point values), so we need to
    divide by the number of floats in a box like we do in the overflow
    case below.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index dda55ea..75c952c 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -189,7 +189,7 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     GLfloat xscale, yscale;
     float vertices[32];
     float *pvertices = vertices;
-    int valid_nbox = ARRAY_SIZE(vertices);
+    int valid_nbox = ARRAY_SIZE(vertices) / (4 * 2);
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
commit d036d22a95b8516a817dd4fa4dd35be363709636
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jan 4 13:28:52 2014 -0800

    glamor: Drop duplicated lines for getting pixmap state in GetImage.
    
    No change in generated code size -- apparently the compiler figured it
    out.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c
index 5609e70..a932473 100644
--- a/glamor/glamor_getimage.c
+++ b/glamor/glamor_getimage.c
@@ -44,8 +44,6 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
 
     if (format != ZPixmap)
         goto fall_back;
-    pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off);
 
     if (!glamor_set_planemask(pixmap, planeMask)) {
         glamor_fallback("Failedto set planemask  in glamor_solid.\n");
commit e23dd41195dfaf1f3e303197845a071d01523618
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 18:41:57 2013 -0800

    glamor: Return the stride/size for glamor_dri3_name_from_pixmap(), too.
    
    Just like for a caller of glamor_dri3_fd_from_pixmap(), otherwise the
    consumer of that named buffer has no idea what GL chose for the
    stride.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index e298b04..5338d45 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -647,7 +647,7 @@ glamor_fd_from_pixmap(ScreenPtr screen,
 }
 
 int
-glamor_name_from_pixmap(PixmapPtr pixmap)
+glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
 {
     glamor_pixmap_private *pixmap_priv;
     glamor_screen_private *glamor_priv =
@@ -663,7 +663,7 @@ glamor_name_from_pixmap(PixmapPtr pixmap)
         return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen,
                                                 pixmap,
                                                 pixmap_priv->base.fbo->tex,
-                                                TRUE, NULL, NULL);
+                                                TRUE, stride, size);
     default:
         break;
     }
diff --git a/glamor/glamor.h b/glamor/glamor.h
index be46a52..d05d2f4 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -210,7 +210,8 @@ extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen,
  *
  * Returns the name on success, -1 on error.
  * */
-extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap);
+extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap,
+                                             CARD16 *stride, CARD32 *size);
 
 /* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd.
  *
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index f3835af..8123421 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -441,10 +441,10 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
     }
     else {
         if (glamor_get_fd_from_bo(glamor_egl->fd, bo, &fd)) {
-            *stride = pixmap->devKind;
-            *size = pixmap->devKind * gbm_bo_get_height(bo);
         }
     }
+    *stride = pixmap->devKind;
+    *size = pixmap->devKind * gbm_bo_get_height(bo);
 
     gbm_bo_destroy(bo);
  failure:
commit 4e21b7ee49bc8f33c6211411d80aa70b16998adc
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 18:33:09 2013 -0800

    glamor: Drop the body of the function for enabling DRI3 extensions.
    
    The flag is already being set at glamor_egl_screen_init() time, so no
    need for the driver to separately call this.  That said, leave the
    function around to keep the ABI compatibility.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 9cda46d..be46a52 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -247,14 +247,6 @@ extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen,
  * */
 extern _X_EXPORT Bool glamor_egl_init(ScrnInfoPtr scrn, int fd);
 
-/* @glamor_egl_init_textured_pixmap: Initialization for textured pixmap allocation.
- *
- * @screen: Current screen pointer.
- *
- * This function must be called before any textured pixmap's creation including
- * the screen pixmap. Could be called from DDX's screenInit function after the calling
- * to glamor_init..
- */
 extern _X_EXPORT Bool glamor_egl_init_textured_pixmap(ScreenPtr screen);
 
 /* @glamor_egl_create_textured_screen: Create textured screen pixmap.
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index f24cb28..f3835af 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -831,14 +831,9 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
     return TRUE;
 }
 
+/** Stub to retain compatibility with pre-server-1.16 ABI. */
 Bool
 glamor_egl_init_textured_pixmap(ScreenPtr screen)
 {
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    struct glamor_egl_screen_private *glamor_egl =
-        glamor_egl_get_screen_private(scrn);
-
-    if (glamor_egl->dri3_capable)
-        glamor_enable_dri3(screen);
     return TRUE;
 }
commit 92e2125c5219c7b270785f063fe2560583b2baff
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 18:29:50 2013 -0800

    sync: Add a header include necessary to use misyncstr.h
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/miext/sync/misyncstr.h b/miext/sync/misyncstr.h
index b5bf6fd..ad69e8e 100644
--- a/miext/sync/misyncstr.h
+++ b/miext/sync/misyncstr.h
@@ -29,6 +29,7 @@
 #define _MISYNCSTR_H_
 
 #include "dix.h"
+#include "misync.h"
 #include "scrnintstr.h"
 #include <X11/extensions/syncconst.h>
 
commit 12b2adaaeb091ad48825f439fa0359e5641c86d1
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Dec 28 13:46:17 2013 -0800

    glamor: Do glyph private init at screeninit time, and other stuff at CSR.
    
    This hasn't actually been a problem, since the server hasn't allocated
    any glyphs before our glyph private initialization during
    CreateScreenResources.  But it's generally not X Server style to do
    things this way.
    
    Now that glamor itself drives both parts of glyphs setup, DDX drivers
    no longer need to tell glamor to initialize glyphs.  We do retain the
    old public symbol so they can keep running with no changes.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index e856179..e298b04 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -271,6 +271,29 @@ glamor_set_debug_level(int *debug_level)
 
 int glamor_debug_level;
 
+/**
+ * Creates any pixmaps used internally by glamor, since those can't be
+ * allocated at ScreenInit time.
+ */
+static Bool
+glamor_create_screen_resources(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    Bool ret = TRUE;
+
+    screen->CreateScreenResources =
+        glamor_priv->saved_procs.create_screen_resources;
+    if (screen->CreateScreenResources)
+        ret = screen->CreateScreenResources(screen);
+    screen->CreateScreenResources = glamor_create_screen_resources;
+
+    if (!glamor_realize_glyph_caches(screen)) {
+        ErrorF("Failed to initialize glyph cache\n");
+        ret = FALSE;
+    }
+
+    return ret;
+}
 
 /** Set up glamor for an already-configured GL context. */
 Bool
@@ -374,6 +397,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_priv->saved_procs.close_screen = screen->CloseScreen;
     screen->CloseScreen = glamor_close_screen;
 
+    glamor_priv->saved_procs.create_screen_resources =
+        screen->CreateScreenResources;
+    screen->CreateScreenResources = glamor_create_screen_resources;
+
     if (flags & GLAMOR_USE_SCREEN) {
         if (!RegisterBlockAndWakeupHandlers(_glamor_block_handler,
                                             _glamor_wakeup_handler,
@@ -457,6 +484,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_init_xv_shader(screen);
 #endif
     glamor_pixmap_init(screen);
+    glamor_glyphs_init(screen);
 
     glamor_priv->flags = flags;
     glamor_priv->screen = screen;
@@ -535,6 +563,8 @@ glamor_close_screen(ScreenPtr screen)
     flags = glamor_priv->flags;
     glamor_glyphs_fini(screen);
     screen->CloseScreen = glamor_priv->saved_procs.close_screen;
+    screen->CreateScreenResources =
+        glamor_priv->saved_procs.create_screen_resources;
     if (flags & GLAMOR_USE_SCREEN) {
 
         screen->CreateGC = glamor_priv->saved_procs.create_gc;
diff --git a/glamor/glamor.h b/glamor/glamor.h
index e25dc73..9cda46d 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -131,14 +131,6 @@ extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap,
 
 extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap);
 
-/* @glamor_glyphs_init: Initialize glyphs internal data structures.
- *
- * @pScreen: Current screen pointer.
- *
- * This function must be called after the glamor_init and the texture
- * can be allocated. An example is to call it when create the screen
- * resources at DDX layer.
- */
 extern _X_EXPORT Bool glamor_glyphs_init(ScreenPtr pScreen);
 
 extern _X_EXPORT void glamor_set_pixmap_texture(PixmapPtr pixmap,
diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index caafa43..2b2c735 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -303,7 +303,7 @@ glamor_glyphs_fini(ScreenPtr pScreen)
  * rest of the allocated structures for all caches with the given format.
  */
 
-static Bool
+Bool
 glamor_realize_glyph_caches(ScreenPtr pScreen)
 {
     glamor_screen_private *glamor = glamor_get_screen_private(pScreen);
@@ -314,10 +314,6 @@ glamor_realize_glyph_caches(ScreenPtr pScreen)
     };
     int i;
 
-    if (glamor->glyph_cache_initialized)
-        return TRUE;
-
-    glamor->glyph_cache_initialized = TRUE;
     memset(glamor->glyphCaches, 0, sizeof(glamor->glyphCaches));
 
     for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) {
@@ -370,16 +366,27 @@ glamor_realize_glyph_caches(ScreenPtr pScreen)
     return FALSE;
 }
 
+/**
+ * Called by glamor_create_screen_resources() to set up the glyph cache.
+ *
+ * This was previously required to be called by the drivers, but not
+ * as of the xserver 1.16 ABI.
+ */
 Bool
 glamor_glyphs_init(ScreenPtr pScreen)
 {
+    glamor_screen_private *glamor = glamor_get_screen_private(pScreen);
+
+    if (glamor->glyph_cache_initialized)
+        return TRUE;
+
     if (!dixRegisterPrivateKey(&glamor_glyph_key,
                                PRIVATE_GLYPH, sizeof(struct glamor_glyph)))
         return FALSE;
 
-    /* Skip pixmap creation if we don't intend to use it. */
+    glamor->glyph_cache_initialized = TRUE;
 
-    return glamor_realize_glyph_caches(pScreen);
+    return TRUE;
 }
 
 /* The most efficient thing to way to upload the glyph to the screen
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 122f4fd..4dc2c75 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -173,6 +173,7 @@ typedef struct {
 
 struct glamor_saved_procs {
     CloseScreenProcPtr close_screen;
+    CreateScreenResourcesProcPtr create_screen_resources;
     CreateGCProcPtr create_gc;
     CreatePixmapProcPtr create_pixmap;
     DestroyPixmapProcPtr destroy_pixmap;
@@ -634,6 +635,7 @@ void glamor_get_spans(DrawablePtr drawable,
                       int nspans, char *dst_start);
 
 /* glamor_glyphs.c */
+Bool glamor_realize_glyph_caches(ScreenPtr screen);
 void glamor_glyphs_fini(ScreenPtr screen);
 void glamor_glyphs(CARD8 op,
                    PicturePtr pSrc,
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 0a9eb46..3260d95 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -1243,9 +1243,6 @@ ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
     if (!ephyr_glamor)
         return TRUE;
 
-    if (!glamor_glyphs_init(pScreen))
-        return FALSE;
-
     /* kdrive's fbSetupScreen() told mi to have
      * miCreateScreenResources() (which is called before this) make a
      * scratch pixmap wrapping ephyr-glamor's NULL
commit df1ef90fa0f98c779c3f312130183dbf32f1e447
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 18:45:44 2013 -0800

    glamor: Move the EGL image to the normal pixmap private.
    
    There's no reason to hide EGL from the rest of glamor, now that we
    have epoxy.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 13799fc..f24cb28 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -54,10 +54,6 @@
 
 static const char glamor_name[] = "glamor";
 
-static DevPrivateKeyRec glamor_egl_pixmap_private_key_index;
-DevPrivateKey glamor_egl_pixmap_private_key =
-    &glamor_egl_pixmap_private_key_index;
-
 static void
 glamor_identify(int flags)
 {
@@ -228,11 +224,13 @@ Bool
 glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_pixmap_private *pixmap_priv;
     struct glamor_egl_screen_private *glamor_egl;
     PixmapPtr screen_pixmap;
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
     screen_pixmap = screen->GetScreenPixmap(screen);
+    pixmap_priv = glamor_get_pixmap_private(screen_pixmap);
 
     if (!glamor_egl_create_textured_pixmap(screen_pixmap, handle, stride)) {
         xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -240,8 +238,7 @@ glamor_egl_create_textured_screen(ScreenPtr screen, int handle, int stride)
         return FALSE;
     }
 
-    glamor_egl->front_image = dixLookupPrivate(&screen_pixmap->devPrivates,
-                                               glamor_egl_pixmap_private_key);
+    glamor_egl->front_image = pixmap_priv->base.image;
     glamor_set_screen_pixmap(screen_pixmap, glamor_egl->back_pixmap);
     return TRUE;
 }
@@ -282,6 +279,8 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_screen_private *glamor_priv =
         glamor_get_screen_private(screen);
+    struct glamor_pixmap_private *pixmap_priv =
+        glamor_get_pixmap_private(pixmap);
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     GLuint texture;
@@ -316,7 +315,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
     glamor_create_texture_from_image(glamor_egl, image, &texture);
     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_texture(pixmap, texture);
-    dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image);
+    pixmap_priv->base.image = image;
     ret = TRUE;
 
  done:
@@ -331,6 +330,8 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_screen_private *glamor_priv =
         glamor_get_screen_private(screen);
+    struct glamor_pixmap_private *pixmap_priv =
+        glamor_get_pixmap_private(pixmap);
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     GLuint texture;
@@ -350,7 +351,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
     glamor_create_texture_from_image(glamor_egl, image, &texture);
     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_texture(pixmap, texture);
-    dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key, image);
+    pixmap_priv->base.image = image;
     ret = TRUE;
 
  done:
@@ -395,6 +396,8 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 {
 #ifdef GLAMOR_HAS_GBM
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_pixmap_private *pixmap_priv =
+        glamor_get_pixmap_private(pixmap);
     struct glamor_screen_private *glamor_priv =
         glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl;
@@ -412,10 +415,8 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     glamor_get_context(glamor_priv);
 
-    image = dixLookupPrivate(&pixmap->devPrivates,
-                             glamor_egl_pixmap_private_key);
-
-    if (image == EGL_NO_IMAGE_KHR || image == NULL) {
+    image = pixmap_priv->base.image;
+    if (!image) {
         image = eglCreateImageKHR(glamor_egl->display,
                                   glamor_egl->context,
                                   EGL_GL_TEXTURE_2D_KHR,
@@ -424,8 +425,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
         if (image == EGL_NO_IMAGE_KHR)
             goto failure;
 
-        dixSetPrivate(&pixmap->devPrivates,
-                      glamor_egl_pixmap_private_key, image);
+        pixmap_priv->base.image = image;
         glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     }
 
@@ -530,20 +530,18 @@ static void
 _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
-    EGLImageKHR image;
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
+    struct glamor_pixmap_private *pixmap_priv =
+        glamor_get_pixmap_private(pixmap);
 
-    image = dixLookupPrivate(&pixmap->devPrivates,
-                             glamor_egl_pixmap_private_key);
-    if (image != EGL_NO_IMAGE_KHR && image != NULL) {
+    if (pixmap_priv->base.image) {
         /* Before destroy an image which was attached to
          * a texture. we must call glFlush to make sure the
          * operation on that texture has been done.*/
         glamor_block_handler(pixmap->drawable.pScreen);
-        eglDestroyImageKHR(glamor_egl->display, image);
-        dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key,
-                      NULL);
+        eglDestroyImageKHR(glamor_egl->display, pixmap_priv->base.image);
+        pixmap_priv->base.image = NULL;
     }
 }
 
@@ -553,21 +551,21 @@ glamor_egl_exchange_buffers(PixmapPtr front, PixmapPtr back)
     ScrnInfoPtr scrn = xf86ScreenToScrn(front->drawable.pScreen);
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
-    EGLImageKHR old_front_image;
-    EGLImageKHR new_front_image;
+    EGLImageKHR temp;
+    struct glamor_pixmap_private *front_priv =
+        glamor_get_pixmap_private(front);
+    struct glamor_pixmap_private *back_priv =
+        glamor_get_pixmap_private(back);
 
     glamor_pixmap_exchange_fbos(front, back);
-    new_front_image =
-        dixLookupPrivate(&back->devPrivates, glamor_egl_pixmap_private_key);
-    old_front_image =
-        dixLookupPrivate(&front->devPrivates, glamor_egl_pixmap_private_key);
-    dixSetPrivate(&front->devPrivates, glamor_egl_pixmap_private_key,
-                  new_front_image);
-    dixSetPrivate(&back->devPrivates, glamor_egl_pixmap_private_key,
-                  old_front_image);
+
+    temp = back_priv->base.image;
+    back_priv->base.image = front_priv->base.image;
+    front_priv->base.image = temp;
+
     glamor_set_pixmap_type(front, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_type(back, GLAMOR_TEXTURE_DRM);
-    glamor_egl->front_image = new_front_image;
+    glamor_egl->front_image = front_priv->base.image;
 
 }
 
@@ -584,24 +582,23 @@ glamor_egl_close_screen(ScreenPtr screen)
 {
     ScrnInfoPtr scrn;
     struct glamor_egl_screen_private *glamor_egl;
+    struct glamor_pixmap_private *pixmap_priv;
     PixmapPtr screen_pixmap;
-    EGLImageKHR back_image;
 
     scrn = xf86ScreenToScrn(screen);
     glamor_egl = glamor_egl_get_screen_private(scrn);
     screen_pixmap = screen->GetScreenPixmap(screen);
+    pixmap_priv = glamor_get_pixmap_private(screen_pixmap);
 
-    eglDestroyImageKHR(glamor_egl->display,glamor_egl->front_image);
-    dixSetPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key,
-                  NULL);
+    eglDestroyImageKHR(glamor_egl->display, glamor_egl->front_image);
+    pixmap_priv->base.image = NULL;
     glamor_egl->front_image = NULL;
+
     if (glamor_egl->back_pixmap && *glamor_egl->back_pixmap) {
-        back_image = dixLookupPrivate(&(*glamor_egl->back_pixmap)->devPrivates,
-                                      glamor_egl_pixmap_private_key);
-        if (back_image != NULL && back_image != EGL_NO_IMAGE_KHR) {
-            eglDestroyImageKHR(glamor_egl->display, back_image);
-            dixSetPrivate(&(*glamor_egl->back_pixmap)->devPrivates,
-                          glamor_egl_pixmap_private_key, NULL);
+        pixmap_priv = glamor_get_pixmap_private(*glamor_egl->back_pixmap);
+        if (pixmap_priv->base.image) {
+            eglDestroyImageKHR(glamor_egl->display, pixmap_priv->base.image);
+            pixmap_priv->base.image = NULL;
         }
     }
 
@@ -840,13 +837,7 @@ glamor_egl_init_textured_pixmap(ScreenPtr screen)
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
-    if (!dixRegisterPrivateKey
-        (glamor_egl_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
-        LogMessage(X_WARNING,
-                   "glamor%d: Failed to allocate egl pixmap private\n",
-                   screen->myNum);
-        return FALSE;
-    }
+
     if (glamor_egl->dri3_capable)
         glamor_enable_dri3(screen);
     return TRUE;
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index d15eabd..122f4fd 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -36,6 +36,10 @@
 #include "glamor.h"
 
 #include <epoxy/gl.h>
+#if GLAMOR_HAS_GBM
+#define MESA_EGL_NO_X11_HEADERS
+#include <epoxy/egl.h>
+#endif
 
 #define GLAMOR_DEFAULT_PRECISION  \
     "#ifdef GL_ES\n"              \
@@ -406,6 +410,9 @@ typedef struct glamor_pixmap_private_base {
     int drm_stride;
     glamor_screen_private *glamor_priv;
     PicturePtr picture;
+#if GLAMOR_HAS_GBM
+    EGLImageKHR image;
+#endif
 } glamor_pixmap_private_base_t;
 
 /*
commit 732faea542c5ecab353536f93bab5dc6c6068d0a
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 18:27:56 2013 -0800

    glamor: Use epoxy_has_egl_extension() instead of rolling our own.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 05e6bd0..13799fc 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -610,25 +610,6 @@ glamor_egl_close_screen(ScreenPtr screen)
     return screen->CloseScreen(screen);
 }
 
-static Bool
-glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl,
-                         const char *extension)
-{
-    const char *pext;
-    int ext_len;
-
-    ext_len = strlen(extension);
-    pext = (const char *) eglQueryString(glamor_egl->display, EGL_EXTENSIONS);
-    if (pext == NULL || extension == NULL)
-        return FALSE;
-    while ((pext = strstr(pext, extension)) != NULL) {
-        if (pext[ext_len] == ' ' || pext[ext_len] == '\0')
-            return TRUE;
-        pext += ext_len;
-    }
-    return FALSE;
-}
-
 static int
 glamor_dri3_open(ScreenPtr screen,
                  RRProviderPtr provider,
@@ -799,14 +780,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
     xf86Msg(X_INFO, "%s: EGL version %s:\n", glamor_name, version);
 
 #define GLAMOR_CHECK_EGL_EXTENSION(EXT)  \
-	if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT)) {  \
+	if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT)) {  \
 		ErrorF("EGL_" #EXT " required.\n");  \
 		return FALSE;  \
 	}
 
 #define GLAMOR_CHECK_EGL_EXTENSIONS(EXT1, EXT2)	 \
-	if (!glamor_egl_has_extension(glamor_egl, "EGL_" #EXT1) &&  \
-	    !glamor_egl_has_extension(glamor_egl, "EGL_" #EXT2)) {  \
+	if (!epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT1) &&  \
+	    !epoxy_has_egl_extension(glamor_egl->display, "EGL_" #EXT2)) {  \
 		ErrorF("EGL_" #EXT1 " or EGL_" #EXT2 " required.\n");  \
 		return FALSE;  \
 	}
@@ -821,8 +802,10 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
 #endif
 
 #ifdef GLAMOR_HAS_GBM
-    if (glamor_egl_has_extension(glamor_egl, "EGL_KHR_gl_texture_2D_image") &&
-        glamor_egl_has_extension(glamor_egl, "EGL_EXT_image_dma_buf_import"))
+    if (epoxy_has_egl_extension(glamor_egl->display,
+                                "EGL_KHR_gl_texture_2D_image") &&
+        epoxy_has_egl_extension(glamor_egl->display,
+                                "EGL_EXT_image_dma_buf_import"))
         glamor_egl->dri3_capable = TRUE;
 #endif
 
commit a895f6a16588024e03218d8d0e77dd8bd8494329
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Jan 5 02:45:05 2014 -0800

    glamor: Drop the set of the context to NULL at the end of glamor ops.
    
    The theory here was that it (which I copied from EGL) existed to fix
    up context switching with indirect GLX.  But indirect GLX won't even
    try to set the context again unless its lastContext field is cleared,
    so we need to solve this a different way.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_glx.c b/glamor/glamor_glx.c
index 311bf75..8f47c3d 100644
--- a/glamor/glamor_glx.c
+++ b/glamor/glamor_glx.c
@@ -53,13 +53,7 @@ glamor_glx_get_context(struct glamor_context *glamor_ctx)
 static void
 glamor_glx_put_context(struct glamor_context *glamor_ctx)
 {
-    if (--glamor_ctx->get_count)
-        return;
-
-    /* We actually reset the context, so that indirect GLX's EGL usage
-     * won't get confused by ours.
-     */
-    glXMakeCurrent(glamor_ctx->display, None, NULL);
+    --glamor_ctx->get_count;
 }
 
 Bool
commit f31911ff8f3f3707101b7771d5dc994ed1ca5c70
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Feb 27 17:55:50 2014 -0800

    xephyr: Don't forget to glViewport() before drawing the screen.
    
    Fixes misrendering with cairogears.  I had noticed the failure while
    trying to figure out what was going on with traps.  Cairogears was
    apparently putting its results on the screen through putimage, which
    is a texture upload, so the last GL drawing was done to the size of
    the cairogears window, not the size of the xephyr screen.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index d56907f..eaf5654 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -67,6 +67,9 @@ struct ephyr_glamor {
     GLuint texture_shader;
     GLuint texture_shader_position_loc;
     GLuint texture_shader_texcoord_loc;
+
+    /* Size of the window that we're rendering to. */
+    unsigned width, height;
 };
 
 static GLint
@@ -205,6 +208,7 @@ ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
     glUseProgram(glamor->texture_shader);
+    glViewport(0, 0, glamor->width, glamor->height);
 
     glVertexAttribPointer(glamor->texture_shader_position_loc,
                           2, GL_FLOAT, FALSE, 0, position);
@@ -329,3 +333,14 @@ ephyr_glamor_get_visual(void)
 
     return xcb_aux_find_visual_by_id(xscreen, visual_info->visualid);
 }
+
+void
+ephyr_glamor_set_window_size(struct ephyr_glamor *glamor,
+                             unsigned width, unsigned height)
+{
+    if (!glamor)
+        return;
+
+    glamor->width = width;
+    glamor->height = height;
+}
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.h b/hw/kdrive/ephyr/ephyr_glamor_glx.h
index 8995e1e..0c238cf 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.h
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.h
@@ -51,6 +51,10 @@ ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor);
 
 #ifdef GLAMOR
 void
+ephyr_glamor_set_window_size(struct ephyr_glamor *glamor,
+                             unsigned width, unsigned height);
+
+void
 ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
                               struct pixman_region16 *damage);
 
@@ -60,6 +64,12 @@ ephyr_glamor_process_event(xcb_generic_event_t *xev);
 #else /* !GLAMOR */
 
 static inline void
+ephyr_glamor_set_window_size(struct ephyr_glamor *glamor,
+                             unsigned width, unsigned height)
+{
+}
+
+static inline void
 ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
                               struct pixman_region16 *damage)
 {
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 859beca..0a9eb46 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -731,6 +731,8 @@ hostx_screen_init(KdScreenInfo *screen,
     if (ephyr_glamor) {
         *bytes_per_line = 0;
         *bits_per_pixel = 0;
+        ephyr_glamor_set_window_size(scrpriv->glamor,
+                                     scrpriv->win_width, scrpriv->win_height);
         return NULL;
     } else if (host_depth_matches_server(scrpriv)) {
         *bytes_per_line = scrpriv->ximg->stride;
@@ -1218,6 +1220,8 @@ ephyr_glamor_init(ScreenPtr screen)
     EphyrScrPriv *scrpriv = kd_screen->driver;
 
     scrpriv->glamor = ephyr_glamor_glx_screen_init(scrpriv->win);
+    ephyr_glamor_set_window_size(scrpriv->glamor,
+                                 scrpriv->win_width, scrpriv->win_height);
 
     glamor_init(screen,
                 GLAMOR_USE_SCREEN |
commit 8b6c79e19cfabd9f343884ddd91a738720c94583
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Mar 12 17:20:17 2014 +1000

    xkb: add KeymapOrDefault
    
    Helper function to return a default map if the keymap compilation failed.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 0361b9b..76bf09c 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -444,6 +444,29 @@ XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, int need)
     return xkb;
 }
 
+static XkbDescPtr
+KeymapOrDefaults(DeviceIntPtr dev, XkbDescPtr xkb)
+{
+    XkbRMLVOSet dflts;
+
+    if (xkb)
+        return xkb;
+
+    /* we didn't get what we really needed. And that will likely leave
+     * us with a keyboard that doesn't work. Use the defaults instead */
+    LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
+                        "keymap instead.\n");
+
+    XkbGetRulesDflts(&dflts);
+
+    xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
+
+    XkbFreeRMLVOSet(&dflts, FALSE);
+
+    return xkb;
+}
+
+
 XkbDescPtr
 XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
 {
@@ -461,20 +484,5 @@ XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
 
     xkb = XkbCompileKeymapForDevice(dev, rmlvo, need);
 
-    if (!xkb) {
-        XkbRMLVOSet dflts;
-
-        /* we didn't get what we really needed. And that will likely leave
-         * us with a keyboard that doesn't work. Use the defaults instead */
-        LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
-                   "keymap instead.\n");
-
-        XkbGetRulesDflts(&dflts);
-
-        xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
-
-        XkbFreeRMLVOSet(&dflts, FALSE);
-    }
-
-    return xkb;
+    return KeymapOrDefaults(dev, xkb);
 }
commit cb9a1d01468732196fd25c6422991e784639ffce
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Wed Mar 12 17:18:22 2014 +1000

    xkb: factor out xkb loading to LoadXkm
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 33247cf..0361b9b 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -291,6 +291,35 @@ XkbDDXOpenConfigFile(const char *mapName, char *fileNameRtrn, int fileNameRtrnLe
     return file;
 }
 
+static unsigned
+LoadXKM(unsigned want, unsigned need, const char *keymap, XkbDescPtr *xkbRtrn)
+{
+    FILE *file;
+    char fileName[PATH_MAX];
+    unsigned missing;
+
+    file = XkbDDXOpenConfigFile(keymap, fileName, PATH_MAX);
+    if (file == NULL) {
+        LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
+                   fileName);
+        return 0;
+    }
+    missing = XkmReadFile(file, need, want, xkbRtrn);
+    if (*xkbRtrn == NULL) {
+        LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
+        fclose(file);
+        (void) unlink(fileName);
+        return 0;
+    }
+    else {
+        DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
+               (*xkbRtrn)->defined);
+    }
+    fclose(file);
+    (void) unlink(fileName);
+    return (need | want) & (~missing);
+}
+
 unsigned
 XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
                         XkbComponentNamesPtr names,
@@ -299,9 +328,6 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
                         XkbDescPtr *xkbRtrn, char *nameRtrn, int nameRtrnLen)
 {
     XkbDescPtr xkb;
-    FILE *file;
-    char fileName[PATH_MAX];
-    unsigned missing;
 
     *xkbRtrn = NULL;
     if ((keybd == NULL) || (keybd->key == NULL) ||
@@ -321,26 +347,8 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
         LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
         return 0;
     }
-    file = XkbDDXOpenConfigFile(nameRtrn, fileName, PATH_MAX);
-    if (file == NULL) {
-        LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
-                   fileName);
-        return 0;
-    }
-    missing = XkmReadFile(file, need, want, xkbRtrn);
-    if (*xkbRtrn == NULL) {
-        LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
-        fclose(file);
-        (void) unlink(fileName);
-        return 0;
-    }
-    else {
-        DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
-               (*xkbRtrn)->defined);
-    }
-    fclose(file);
-    (void) unlink(fileName);
-    return (need | want) & (~missing);
+
+    return LoadXKM(want, need, nameRtrn, xkbRtrn);
 }
 
 Bool
commit 4391cf27f40ec53d41ac7e437cde49848eb32bde
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Mar 12 16:08:15 2014 +1000

    xkb: add a callback to xkbcomp
    
    This provides a callback to write to xkbcomp's buffer once everything is
    prepared.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index 551f20a..33247cf 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -90,11 +90,17 @@ OutputDirectory(char *outdir, size_t size)
     }
 }
 
-static Bool
-XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
-                           XkbComponentNamesPtr names,
-                           unsigned want,
-                           unsigned need, char *nameRtrn, int nameRtrnLen)
+/**
+ * Callback invoked by XkbRunXkbComp. Write to out to talk to xkbcomp.
+ */
+typedef void (*xkbcomp_buffer_callback)(FILE *out, void *userdata);
+
+/**
+ * Start xkbcomp, let the callback write into xkbcomp's stdin. When done,
+ * return a strdup'd copy of the file name we've written to.
+ */
+static char *
+RunXkbComp(xkbcomp_buffer_callback callback, void *userdata)
 {
     FILE *out;
     char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
@@ -155,7 +161,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
     if (!buf) {
         LogMessage(X_ERROR,
                    "XKB: Could not invoke xkbcomp: not enough memory\n");
-        return FALSE;
+        return NULL;
     }
 
 #ifndef WIN32
@@ -165,13 +171,9 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
 #endif
 
     if (out != NULL) {
-#ifdef DEBUG
-        if (xkbDebugFlags) {
-            ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
-            XkbWriteXKBKeymapForNames(stderr, names, xkb, want, need);
-        }
-#endif
-        XkbWriteXKBKeymapForNames(out, names, xkb, want, need);
+        /* Now write to xkbcomp */
+        (*callback)(out, userdata);
+
 #ifndef WIN32
         if (Pclose(out) == 0)
 #else
@@ -180,14 +182,11 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
         {
             if (xkbDebugFlags)
                 DebugF("[xkb] xkb executes: %s\n", buf);
-            if (nameRtrn) {
-                strlcpy(nameRtrn, keymap, nameRtrnLen);
-            }
             free(buf);
 #ifdef WIN32
             unlink(tmpname);
 #endif
-            return TRUE;
+            return xnfstrdup(keymap);
         }
         else
             LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
@@ -203,10 +202,57 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
         LogMessage(X_ERROR, "Could not open file %s\n", tmpname);
 #endif
     }
-    if (nameRtrn)
-        nameRtrn[0] = '\0';
     free(buf);
-    return FALSE;
+    return NULL;
+}
+
+typedef struct {
+    XkbDescPtr xkb;
+    XkbComponentNamesPtr names;
+    unsigned int want;
+    unsigned int need;
+} XkbKeymapNamesCtx;
+
+static void
+xkb_write_keymap_for_names_cb(FILE *out, void *userdata)
+{
+    XkbKeymapNamesCtx *ctx = userdata;
+#ifdef DEBUG
+    if (xkbDebugFlags) {
+        ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
+        XkbWriteXKBKeymapForNames(stderr, ctx->names, ctx->xkb, ctx->want, ctx->need);
+    }
+#endif
+    XkbWriteXKBKeymapForNames(out, ctx->names, ctx->xkb, ctx->want, ctx->need);
+}
+
+static Bool
+XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
+                           XkbComponentNamesPtr names,
+                           unsigned want,
+                           unsigned need, char *nameRtrn, int nameRtrnLen)
+{
+    char *keymap;
+    Bool rc = FALSE;
+    XkbKeymapNamesCtx ctx = {
+        .xkb = xkb,
+        .names = names,
+        .want = want,
+        .need = need
+    };
+
+    keymap = RunXkbComp(xkb_write_keymap_for_names_cb, &ctx);
+
+    if (keymap) {
+        if(nameRtrn)
+            strlcpy(nameRtrn, keymap, nameRtrnLen);
+
+        free(keymap);
+        rc = TRUE;
+    } else if (nameRtrn)
+        *nameRtrn = '\0';
+
+    return rc;
 }
 
 static FILE *
commit 6ebd838d80074075827dedb75ed4169ea1946be3
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Mar 12 17:17:25 2014 +1000

    xkb: constify XkbDDXOpenConfigFile
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index f458e3b..551f20a 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -210,7 +210,7 @@ XkbDDXCompileKeymapByNames(XkbDescPtr xkb,
 }
 
 static FILE *
-XkbDDXOpenConfigFile(char *mapName, char *fileNameRtrn, int fileNameRtrnLen)
+XkbDDXOpenConfigFile(const char *mapName, char *fileNameRtrn, int fileNameRtrnLen)
 {
     char buf[PATH_MAX], xkm_output_dir[PATH_MAX];
     FILE *file;
commit 2b77b208daf9402472ba7fb709156a14eb487299
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 12 16:00:23 2014 +0100

    xf86Xinput: release server managed fd before removing the device from the list
    
    So that the fd in use test in systemd_logind_release_fd works properly.
    
    Note we cannot change the test inside systemd_logind_release_fd as it must
    work for devices which were never added to the xf86InputDevs too.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 36b92a9..a367ae3 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -766,6 +766,11 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
 
     FreeInputAttributes(pInp->attrs);
 
+    if (pInp->flags & XI86_SERVER_FD) {
+        systemd_logind_release_fd(pInp->major, pInp->minor);
+        close(pInp->fd);
+    }
+
     /* Remove the entry from the list. */
     if (pInp == xf86InputDevs)
         xf86InputDevs = pInp->next;
@@ -779,11 +784,6 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
         /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
     }
 
-    if (pInp->flags & XI86_SERVER_FD) {
-        systemd_logind_release_fd(pInp->major, pInp->minor);
-        close(pInp->fd);
-    }
-
     free((void *) pInp->driver);
     free((void *) pInp->name);
     xf86optionListFree(pInp->options);
commit 0e972b6037d3709c13d46adef9d14b702f477abc
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 12 14:57:24 2014 +0100

    systemd-logind: Correctly deal with InputDevs sharing a device-node
    
    InputDevices may share a single device-node, this happens ie with Wacom
    tablets.
    
    This patch makes take_fd and release_fd properly deal with this, together
    with the earlier patch for updating the fd in all matching xf86InputDevs
    on pause / resume this completes support for such shared device-nodes.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index a2ef7af..62858b0 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -87,6 +87,7 @@ systemd_logind_take_fd(int _major, int _minor, const char *path,
                        Bool *paused_ret)
 {
     struct systemd_logind_info *info = &logind_info;
+    InputInfoPtr pInfo;
     DBusError error;
     DBusMessage *msg = NULL;
     DBusMessage *reply = NULL;
@@ -102,6 +103,16 @@ systemd_logind_take_fd(int _major, int _minor, const char *path,
     if (strstr(path, "mouse"))
         return -1;
 
+    /* Check if we already have an InputInfo entry with this major, minor
+     * (shared device-nodes happen ie with Wacom tablets). */
+    pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
+    if (pInfo) {
+        LogMessage(X_INFO, "systemd-logind: returning pre-existing fd for %s %u:%u\n",
+               path, major, minor);
+        *paused_ret = FALSE;
+        return pInfo->fd;
+    }
+
     dbus_error_init(&error);
 
     msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
@@ -154,15 +165,31 @@ void
 systemd_logind_release_fd(int _major, int _minor)
 {
     struct systemd_logind_info *info = &logind_info;
+    InputInfoPtr pInfo;
     DBusError error;
     DBusMessage *msg = NULL;
     DBusMessage *reply = NULL;
     dbus_int32_t major = _major;
     dbus_int32_t minor = _minor;
+    int matches = 0;
 
     if (!info->session || major == 0)
         return;
 
+    /* Only release the fd if there is only 1 InputInfo left for this major
+     * and minor, otherwise other InputInfo's are still referencing the fd. */
+    pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
+    while (pInfo) {
+        matches++;
+        pInfo = systemd_logind_find_info_ptr_by_devnum(pInfo->next, major, minor);
+    }
+    if (matches > 1) {
+        LogMessage(X_INFO, "systemd-logind: not releasing fd for %u:%u, still in use\n", major, minor);
+        return;
+    }
+
+    LogMessage(X_INFO, "systemd-logind: releasing fd for %u:%u\n", major, minor);
+
     dbus_error_init(&error);
 
     msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
commit 8d3f63dbe9bfd816beb6475fd0e00df4dbba269f
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 12 12:58:22 2014 +0100

    systemd-logind: Add a systemd_logind_set_input_fd_for_all_devs helper
    
    And use it where appropriate.
    
    Setting the fd for all matching InputDevices is necessary when we've
    multiple InputDevices sharing a single device-node, such as happens with
    Wacom tablets.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index 012a920..a2ef7af 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -65,6 +65,23 @@ systemd_logind_find_info_ptr_by_devnum(InputInfoPtr start,
     return NULL;
 }
 
+static void
+systemd_logind_set_input_fd_for_all_devs(int major, int minor, int fd,
+                                         Bool enable)
+{
+    InputInfoPtr pInfo;
+
+    pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs, major, minor);
+    while (pInfo) {
+        pInfo->fd = fd;
+        pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+        if (enable)
+            xf86EnableInputDeviceForVTSwitch(pInfo);
+
+        pInfo = systemd_logind_find_info_ptr_by_devnum(pInfo->next, major, minor);
+    }
+}
+
 int
 systemd_logind_take_fd(int _major, int _minor, const char *path,
                        Bool *paused_ret)
@@ -337,8 +354,7 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data)
             pdev->flags |= XF86_PDEV_PAUSED;
         else {
             close(pInfo->fd);
-            pInfo->fd = -1;
-            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", -1);
+            systemd_logind_set_input_fd_for_all_devs(major, minor, -1, FALSE);
         }
         if (ack)
             systemd_logind_ack_pause(info, major, minor);
@@ -347,15 +363,12 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data)
         /* info->vt_active gets set by systemd_logind_vtenter() */
         info->active = TRUE;
 
-        if (pdev) {
+        if (pdev)
             pdev->flags &= ~XF86_PDEV_PAUSED;
-        }
-        else {
-            pInfo->fd = fd;
-            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
-            if (info->vt_active)
-                xf86EnableInputDeviceForVTSwitch(pInfo);
-        }
+        else
+            systemd_logind_set_input_fd_for_all_devs(major, minor, fd,
+                                                     info->vt_active);
+
         /* Always call vtenter(), in case there are only legacy video devs */
         systemd_logind_vtenter();
     }
commit 4e3d9690e1868d286dcb766b429f9c99313f2401
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 12 13:19:32 2014 +0100

    systemd_logind_find_info_ptr_by_devnum: Move to higher inside the file
    
    This is a preparation patch for adding support for server managed fds
    for InputDevices where multiple input devices share the same device node (and
    thus also their major and minor).
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index 09db336..012a920 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -51,6 +51,20 @@ struct systemd_logind_info {
 
 static struct systemd_logind_info logind_info;
 
+static InputInfoPtr
+systemd_logind_find_info_ptr_by_devnum(InputInfoPtr start,
+                                       int major, int minor)
+{
+    InputInfoPtr pInfo;
+
+    for (pInfo = start; pInfo; pInfo = pInfo->next)
+        if (pInfo->major == major && pInfo->minor == minor &&
+                (pInfo->flags & XI86_SERVER_FD))
+            return pInfo;
+
+    return NULL;
+}
+
 int
 systemd_logind_take_fd(int _major, int _minor, const char *path,
                        Bool *paused_ret)
@@ -203,20 +217,6 @@ systemd_logind_vtenter(void)
     xf86InputEnableVTProbe();
 }
 
-static InputInfoPtr
-systemd_logind_find_info_ptr_by_devnum(InputInfoPtr start,
-                                       int major, int minor)
-{
-    InputInfoPtr pInfo;
-
-    for (pInfo = start; pInfo; pInfo = pInfo->next)
-        if (pInfo->major == major && pInfo->minor == minor &&
-                (pInfo->flags & XI86_SERVER_FD))
-            return pInfo;
-
-    return NULL;
-}
-
 static void
 systemd_logind_ack_pause(struct systemd_logind_info *info,
                          dbus_int32_t minor, dbus_int32_t major)
commit ddc3888bbaaddc47706a9cb96459738683d72cb3
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 12 12:45:40 2014 +0100

    systemd_logind_find_info_ptr_by_devnum: Add a start argument
    
    Modify systemd_logind_find_info_ptr_by_devnum to take a start argument, so
    that it can be used to find all occurences of a devnum in an InputInfo list,
    rather then just the first.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index a8406d8..09db336 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -204,11 +204,12 @@ systemd_logind_vtenter(void)
 }
 
 static InputInfoPtr
-systemd_logind_find_info_ptr_by_devnum(int major, int minor)
+systemd_logind_find_info_ptr_by_devnum(InputInfoPtr start,
+                                       int major, int minor)
 {
     InputInfoPtr pInfo;
 
-    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+    for (pInfo = start; pInfo; pInfo = pInfo->next)
         if (pInfo->major == major && pInfo->minor == minor &&
                 (pInfo->flags & XI86_SERVER_FD))
             return pInfo;
@@ -320,7 +321,8 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data)
 
     pdev = xf86_find_platform_device_by_devnum(major, minor);        
     if (!pdev)
-        pInfo = systemd_logind_find_info_ptr_by_devnum(major, minor);
+        pInfo = systemd_logind_find_info_ptr_by_devnum(xf86InputDevs,
+                                                       major, minor);
     if (!pdev && !pInfo) {
         LogMessage(X_WARNING, "systemd-logind: could not find dev %u:%u\n",
                    major, minor);
commit 40e3c79a591909ab64822cc86fd07513317bf19b
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 11 11:38:09 2014 +0100

    Remove config_odev_add_*attribute checks in various places
    
    Note that there are more callers but those were already not doing any
    error checking.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/udev.c b/config/udev.c
index d88abaa..a1b72c1 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -55,7 +55,7 @@
 static struct udev_monitor *udev_monitor;
 
 #ifdef CONFIG_UDEV_KMS
-static Bool
+static void
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
                                int major, int minor,
                                config_odev_probe_proc_ptr probe_callback);
@@ -457,40 +457,20 @@ config_udev_fini(void)
 
 #ifdef CONFIG_UDEV_KMS
 
-static Bool
+static void
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
                                int major, int minor,
                                config_odev_probe_proc_ptr probe_callback)
 {
     struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
-    int ret;
-
-    if (!attribs)
-        return FALSE;
-
-    ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_PATH, path);
-    if (ret == FALSE)
-        goto fail;
-
-    ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_SYSPATH, syspath);
-    if (ret == FALSE)
-        goto fail;
-
-    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
-    if (ret == FALSE)
-        goto fail;
 
-    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
-    if (ret == FALSE)
-        goto fail;
+    config_odev_add_attribute(attribs, ODEV_ATTRIB_PATH, path);
+    config_odev_add_attribute(attribs, ODEV_ATTRIB_SYSPATH, syspath);
+    config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
+    config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
 
     /* ownership of attribs is passed to probe layer */
     probe_callback(attribs);
-    return TRUE;
-fail:
-    config_odev_free_attributes(attribs);
-    free(attribs);
-    return FALSE;
 }
 
 void
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 109a9a7..dbd7aa0 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -40,10 +40,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
             systemd_logind_release_fd(major, minor);
             return FALSE;
         }
-        if (!config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd)) {
-            systemd_logind_release_fd(major, minor);
-            return FALSE;
-        }
+        config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd);
         server_fd = TRUE;
     }
 
commit 92ff79f1a804d63d2f2bb59dfbf3a2869627609a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 11 11:28:15 2014 +0100

    config_odev*: Use XNF alloc functions
    
    config_odev* functions are called in code-paths were we already use
    XNF* functions in other places, so which are not oom safe already.
    
    Besides that oom is something which should simply never happen, so aborting
    when it does is as good a response as any other.
    
    While switching to XNF functions also fixup an unchecked strdup case.
    
    Note the function prototypes are kept unchanged, as they are part of the
    server ABI.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 46f2532..def7f16 100644
--- a/config/config.c
+++ b/config/config.c
@@ -132,10 +132,7 @@ config_odev_allocate_attribute_list(void)
 {
     struct OdevAttributes *attriblist;
 
-    attriblist = malloc(sizeof(struct OdevAttributes));
-    if (!attriblist)
-        return NULL;
-
+    attriblist = XNFalloc(sizeof(struct OdevAttributes));
     xorg_list_init(&attriblist->list);
     return attriblist;
 }
@@ -168,10 +165,7 @@ config_odev_find_or_add_attribute(struct OdevAttributes *attribs, int attrib)
     if (oa)
         return oa;
 
-    oa = calloc(1, sizeof(struct OdevAttribute));
-    if (!oa)
-        return oa;
-
+    oa = XNFcalloc(sizeof(struct OdevAttribute));
     oa->attrib_id = attrib;
     xorg_list_append(&oa->member, &attribs->list);
 
@@ -185,11 +179,8 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
     struct OdevAttribute *oa;
 
     oa = config_odev_find_or_add_attribute(attribs, attrib);
-    if (!oa)
-        return FALSE;
-
     free(oa->attrib_name);
-    oa->attrib_name = strdup(attrib_name);
+    oa->attrib_name = XNFstrdup(attrib_name);
     oa->attrib_type = ODEV_ATTRIB_STRING;
     return TRUE;
 }
@@ -201,9 +192,6 @@ config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
     struct OdevAttribute *oa;
 
     oa = config_odev_find_or_add_attribute(attribs, attrib);
-    if (!oa)
-        return FALSE;
-
     oa->attrib_value = attrib_value;
     oa->attrib_type = ODEV_ATTRIB_INT;
     return TRUE;
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 78b5a5b..5dee4e0 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -54,11 +54,12 @@ xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned);
 extern int
 xf86_remove_platform_device(int dev_index);
 extern Bool
+xf86_get_platform_device_unowned(int index);
+/* Note starting with xserver 1.16 these 2 functions never fail */
+extern Bool
 xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
 extern Bool
 xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value);
-extern Bool
-xf86_get_platform_device_unowned(int index);
 
 extern int
 xf86platformAddDevice(int index);
diff --git a/include/hotplug.h b/include/hotplug.h
index 1d9364e..cefc164 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -48,12 +48,14 @@ struct OdevAttributes {
     struct xorg_list list;
 };
 
+/* Note starting with xserver 1.16 this function never fails */
 struct OdevAttributes *
 config_odev_allocate_attribute_list(void);
 
 void
 config_odev_free_attribute_list(struct OdevAttributes *attribs);
 
+/* Note starting with xserver 1.16 this function never fails */
 Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name);
@@ -61,6 +63,7 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
 char *
 config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
 
+/* Note starting with xserver 1.16 this function never fails */
 Bool
 config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
                               int attrib_value);
commit e7b84ca46944895971a8f048c7e34869b7de01c0
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 5 16:41:14 2014 +0100

    Xorg: Add a suid root wrapper
    
    With the recent systemd-logind changes it is possible to install the Xorg
    binary without suid root rights and still have everything working as it
    should *if* the user only has cards which are supported by kms.
    
    This commit adds a little suid root wrapper, which is a bit weird, first we
    strip the suid-root bit of the Xorg binary, and then we add a wrapper ?
    
    The function of this wrapper is to see if a system still needs root-rights,
    if it does not (it supports kms and the kms drivers are properly loaded),
    then it will immediately drop all elevated rights before executing the real
    Xorg binary. If it finds (some) cards which don't support kms, or no cards
    at all, then it will execute the Xorg server with elevated rights so that
    ie the nvidia binary driver and the vesa driver can keep working normally.
    
    To make it possible for security concious users who don't need the root
    rights to completely remove the wrapper, Xorg is started in a 3 step process
    when the wrapper is enabled during build time:
    
    1) A simple shell script which checks if the wrapper is there, if it is
      it executes the wrapper, if not it directly executes the real Xorg binary
    
    2) The wrapper gets executed, does its checks, normally drops all elevated
      rights and then executes the real Xorg binary
    
    3) The real Xorg binary does its thing
    
    This allows distributions to put the wrapper binary in a separate package, and
    will allow users to remove this package. IE the plan with Fedora is to make
    "legacy" drivers depend on the wrapper pkg, and since our default install
    contains some legacy drivers it will be part of the default install, but
    users can later yum remove it (which will also automatically remove the
    legacy driver packages as those won't work without it anyways).
    
    The wrapper is loosely modelled after the existing Debian Xwrapper, it
    uses the same config-file + config-file format, and also allows restricting
    Xserver execution (through the wrapper) to console users only.
    
    There also is a new needs_root_rights config file directive, which can
    be used to override the auto-detection the wrapper does.
    
    Hopefully this will allow Debian to replace their own wrapper with this
    upstream one.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index 162c0cf..749fa84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -627,6 +627,7 @@ AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with p
 AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
 AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
 AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
+AC_ARG_ENABLE(suid-wrapper, AC_HELP_STRING([--enable-suid-wrapper], [Build suid-root wrapper for legacy driver support on rootless xserver systems (default: no)]), [SUID_WRAPPER=$enableval], [SUID_WRAPPER=no])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -924,6 +925,16 @@ if test "x$SYSTEMD_LOGIND" = xyes; then
 fi
 AM_CONDITIONAL(SYSTEMD_LOGIND, [test "x$SYSTEMD_LOGIND" = xyes])
 
+if test "x$SUID_WRAPPER" = xyes; then
+        dnl The wrapper uses libdrm headers, so ensure they are available
+        PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
+        dnl This is a define so that if some platforms want to put the wrapper
+        dnl somewhere else this can be easily changed
+        AC_DEFINE_DIR(SUID_WRAPPER_DIR, libexecdir, [Where to install Xorg.bin and Xorg.wrap])
+        SETUID="no"
+fi
+AM_CONDITIONAL(SUID_WRAPPER, [test "x$SUID_WRAPPER" = xyes])
+
 if test "x$NEED_DBUS" = xyes; then
         AC_DEFINE(NEED_DBUS, 1, [Enable D-Bus core])
 fi
@@ -2116,7 +2127,6 @@ fi
 AC_MSG_RESULT([$XWIN])
 
 if test "x$XWIN" = xyes; then
-	AC_DEFINE_DIR(SYSCONFDIR, sysconfdir, [Location of system.XWinrc])
 	AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location])
 	AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
 	AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
@@ -2440,6 +2450,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 	[ Enable GNU and other extensions to the C environment for glibc])])
 
 AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix])
+AC_DEFINE_DIR(SYSCONFDIR, sysconfdir, [sysconfdir])
 
 AC_SUBST([RELEASE_DATE])
 BUILD_DATE="`date +'%Y%m%d'`"
@@ -2499,6 +2510,7 @@ dri3/Makefile
 present/Makefile
 hw/Makefile
 hw/xfree86/Makefile
+hw/xfree86/Xorg.sh
 hw/xfree86/common/Makefile
 hw/xfree86/common/xf86Build.h
 hw/xfree86/ddc/Makefile
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 73e1b4c..a315bbc 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -81,9 +81,15 @@ Xorg_DEPENDENCIES = $(LOCAL_LIBS)
 
 Xorg_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 
+if SUID_WRAPPER
+wrapdir = $(SUID_WRAPPER_DIR)
+wrap_PROGRAMS = Xorg.wrap
+Xorg_wrap_SOURCES = xorg-wrapper.c
+endif
+
 BUILT_SOURCES = xorg.conf.example
 DISTCLEANFILES = xorg.conf.example
-EXTRA_DIST = xorgconf.cpp
+EXTRA_DIST = xorgconf.cpp Xorg.sh.in
 
 # Without logdir, X will post an error on the terminal and will not start
 install-data-local:
@@ -98,6 +104,11 @@ if INSTALL_SETUID
 	chown root $(DESTDIR)$(bindir)/Xorg
 	chmod u+s $(DESTDIR)$(bindir)/Xorg
 endif
+if SUID_WRAPPER
+	mv $(DESTDIR)$(bindir)/Xorg $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.bin
+	${INSTALL} -m 755 Xorg.sh $(DESTDIR)$(bindir)/Xorg
+	-chown root $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.wrap && chmod u+s $(DESTDIR)$(SUID_WRAPPER_DIR)/Xorg.wrap
+endif
 
 uninstall-local:
 if CYGWIN
@@ -119,7 +130,7 @@ xorg.conf.example: xorgconf.cpp
 relink:
 	$(AM_V_at)rm -f Xorg$(EXEEXT) && $(MAKE) Xorg$(EXEEXT)
 
-CLEANFILES = sdksyms.c sdksyms.dep
+CLEANFILES = sdksyms.c sdksyms.dep Xorg.sh
 EXTRA_DIST += sdksyms.sh
 
 sdksyms.dep sdksyms.c: sdksyms.sh
diff --git a/hw/xfree86/Xorg.sh.in b/hw/xfree86/Xorg.sh.in
new file mode 100644
index 0000000..cef4859
--- /dev/null
+++ b/hw/xfree86/Xorg.sh.in
@@ -0,0 +1,11 @@
+#!/bin/sh
+#
+# Execute Xorg.wrap if it exists otherwise execute Xorg.bin directly.
+# This allows distros to put the suid wrapper in a separate package.
+
+basedir=@SUID_WRAPPER_DIR@
+if [ -x "$basedir"/Xorg.wrap ]; then
+	exec "$basedir"/Xorg.wrap "$@"
+else
+	exec "$basedir"/Xorg.bin "$@"
+fi
diff --git a/hw/xfree86/man/Makefile.am b/hw/xfree86/man/Makefile.am
index 80e22cb..f41d26c 100644
--- a/hw/xfree86/man/Makefile.am
+++ b/hw/xfree86/man/Makefile.am
@@ -1,3 +1,8 @@
 include $(top_srcdir)/manpages.am
 appman_PRE = Xorg.man
 fileman_PRE = xorg.conf.man xorg.conf.d.man
+
+if SUID_WRAPPER
+appman_PRE += Xorg.wrap.man
+fileman_PRE += Xwrapper.config.man
+endif
diff --git a/hw/xfree86/man/Xorg.wrap.man b/hw/xfree86/man/Xorg.wrap.man
new file mode 100644
index 0000000..f2153e3
--- /dev/null
+++ b/hw/xfree86/man/Xorg.wrap.man
@@ -0,0 +1,67 @@
+.\" Xwrapper.wrap.1
+.\"
+.\" Copyright 2014 Red Hat, 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.
+.\"
+.\" The above copyright notice and this permission notice 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 OPEN GROUP 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.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall
+.\" not be used in advertising or otherwise to promote the sale, use or
+.\" other dealings in this Software without prior written authorization
+.\" from The Open Group.
+.\"
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH Xorg.wrap 1 __xorgversion__
+.SH NAME
+Xorg.wrap \- Xorg X server binary wrapper
+.SH DESCRIPTION
+The Xorg X server may need root rights to function properly. To start the
+Xorg X server with these rights your system is using a suid root wrapper
+installed as __suid_wrapper_dir__/Xorg.wrap which will execute the real
+X server which is installed as __suid_wrapper_dir__/Xorg.bin .
+.PP
+By default Xorg.wrap will autodetect if root rights are necessary, and
+if not it will drop its elevated rights before starting the real X server.
+By default Xorg.wrap will only allow executing the real X server from login
+sessions on a physical console.
+
+.SH CONFIG FILE
+Xorg.wrap's default behavior can be overridden from the
+\fI__sysconfdir__/X11/Xwrapper.config\fP config file. Lines starting with a
+\fB#\fP in Xwrapper.config are considered comments and will be ignored. Any
+other non empty lines must take the form of \fBkey\fP = \fIvalue\fP.
+.TP 8
+\fBallowed_users\fP = \fIrootonly\fP|\fIconsole\fP|\fIanybody\fP
+Specify which users may start the X server through the wrapper. Use
+\fIrootonly\fP to only allow root, use \fIconsole\fP to only allow users
+logged into a physical console, and use \fIanybody\fP to allow anybody.
+The default is \fIconsole\fP.
+.TP 8
+\fBneeds_root_rights\fP = \fIyes\fP|\fIno\fP|\fIauto\fP
+Configure if the wrapper should drop its elevated (root) rights before starting
+the X server. Use \fIyes\fP to force execution as root, \fIno\fP to force
+execution with all suid rights dropped, and \fIauto\fP to letter the wrapper
+auto-detect. The default is \fIauto\fP.
+.PP
+When auto-detecting the wrapper will drop rights if kms graphics are available
+and not drop them if no kms graphics are detected. If a system has multiple
+graphics cards and some are not kms capable auto-detection may fail,
+in this case manual configuration should be used.
+
+.SH "SEE ALSO"
+Xorg X server information: \fIXorg\fP(1)
diff --git a/hw/xfree86/man/Xwrapper.config.man b/hw/xfree86/man/Xwrapper.config.man
new file mode 100644
index 0000000..800947c
--- /dev/null
+++ b/hw/xfree86/man/Xwrapper.config.man
@@ -0,0 +1 @@
+.so man1/Xorg.wrap.1
diff --git a/hw/xfree86/xorg-wrapper.c b/hw/xfree86/xorg-wrapper.c
new file mode 100644
index 0000000..90c8c11
--- /dev/null
+++ b/hw/xfree86/xorg-wrapper.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Hans de Goede <hdegoede at redhat.com>
+ */
+
+#include "dix-config.h"
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <drm/drm.h>
+#include <xf86drm.h> /* For DRM_DEV_NAME */
+
+#define CONFIG_FILE SYSCONFDIR "/X11/Xwrapper.config"
+
+enum { ROOT_ONLY, CONSOLE_ONLY, ANYBODY };
+
+/* KISS non locale / LANG parsing isspace version */
+static int is_space(char c)
+{
+    return c == ' ' || c == '\t' || c == '\n';
+}
+
+static char *strip(char *s)
+{
+    int i;
+
+    /* Strip leading whitespace */
+    while (s[0] && is_space(s[0]))
+        s++;
+
+    /* Strip trailing whitespace */
+    i = strlen(s) - 1;
+    while (i >= 0 && is_space(s[i])) {
+        s[i] = 0;
+        i--;
+    }
+
+    return s;
+}
+
+static void parse_config(int *allowed, int *needs_root_rights)
+{
+    FILE *f;
+    char buf[1024];
+    char *stripped, *equals, *key, *value;
+    int line = 0;
+
+    f = fopen(CONFIG_FILE, "r");
+    if (!f)
+        return;
+
+    while (fgets(buf, sizeof(buf), f)) {
+        line++;
+
+        /* Skip comments and empty lines */
+        stripped = strip(buf);
+        if (stripped[0] == '#' || stripped[0] == 0)
+            continue;
+
+        /* Split in a key + value pair */
+        equals = strchr(stripped, '=');
+        if (!equals) {
+            fprintf(stderr, "Syntax error at %s line %d\n", CONFIG_FILE, line);
+            exit(1);
+        }
+        *equals = 0;
+        key   = strip(stripped);   /* To remove trailing whitespace from key */
+        value = strip(equals + 1); /* To remove leading whitespace from val */
+        if (!key[0]) {
+            fprintf(stderr, "Missing key at %s line %d\n", CONFIG_FILE, line);
+            exit(1);
+        }
+        if (!value[0]) {
+            fprintf(stderr, "Missing value at %s line %d\n", CONFIG_FILE, line);
+            exit(1);
+        }
+
+        /* And finally process */
+        if (strcmp(key, "allowed_users") == 0) {
+            if (strcmp(value, "rootonly") == 0)
+                *allowed = ROOT_ONLY;
+            else if (strcmp(value, "console") == 0)
+                *allowed = CONSOLE_ONLY;
+            else if (strcmp(value, "anybody") == 0)
+                *allowed = ANYBODY;
+            else {
+                fprintf(stderr,
+                    "Invalid value '%s' for 'allowed_users' at %s line %d\n",
+                    value, CONFIG_FILE, line);
+                exit(1);
+            }
+        }
+        else if (strcmp(key, "needs_root_rights") == 0) {
+            if (strcmp(value, "yes") == 0)
+                *needs_root_rights = 1;
+            else if (strcmp(value, "no") == 0)
+                *needs_root_rights = 0;
+            else if (strcmp(value, "auto") == 0)
+                *needs_root_rights = -1;
+            else {
+                fprintf(stderr,
+                    "Invalid value '%s' for 'needs_root_rights' at %s line %d\n",
+                    value, CONFIG_FILE, line);
+                exit(1);
+            }
+        }
+        else if (strcmp(key, "nice_value") == 0) {
+            /* Backward compatibility with older Debian Xwrapper, ignore */
+        }
+        else {
+            fprintf(stderr, "Invalid key '%s' at %s line %d\n", key,
+                    CONFIG_FILE, line);
+            exit(1);
+        }
+    }
+    fclose(f);
+}
+
+int main(int argc, char *argv[])
+{
+    struct drm_mode_card_res res;
+    struct stat st;
+    char buf[PATH_MAX];
+    int i, r, fd;
+    int kms_cards = 0;
+    int total_cards = 0;
+    int allowed = CONSOLE_ONLY;
+    int needs_root_rights = -1;
+
+    parse_config(&allowed, &needs_root_rights);
+
+    /* For non root users check if they are allowed to run the X server */
+    if (getuid() != 0) {
+        switch (allowed) {
+        case ROOT_ONLY:
+            /* Already checked above */
+            fprintf(stderr, "%s: Only root is allowed to run the X server\n", argv[0]);
+            exit(1);
+            break;
+        case CONSOLE_ONLY:
+            /* Some of stdin / stdout / stderr maybe redirected to a file */
+            for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+                r = fstat(i, &st);
+                if (r == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4)
+                    break;
+            }
+            if (i > STDERR_FILENO) {
+                fprintf(stderr, "%s: Only console users are allowed to run the X server\n", argv[0]);
+                exit(1);
+            }
+            break;
+        case ANYBODY:
+            break;
+        }
+    }
+
+    /* Detect if we need root rights, except when overriden by the config */
+    if (needs_root_rights == -1) {
+        for (i = 0; i < 16; i++) {
+            snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, i);
+            fd = open(buf, O_RDWR);
+            if (fd == -1)
+                continue;
+
+            total_cards++;
+
+            memset(&res, 0, sizeof(struct drm_mode_card_res));
+            r = ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
+            if (r == 0 && res.count_connectors > 0)
+                kms_cards++;
+
+            close(fd);
+        }
+    }
+
+    /* If we've found cards, and all cards support kms, drop root rights */
+    if (needs_root_rights == 0 || (total_cards && kms_cards == total_cards)) {
+        gid_t realgid = getgid();
+        uid_t realuid = getuid();
+
+        if (setresgid(-1, realgid, realgid) != 0) {
+            perror("Could not drop setgid privileges");
+            exit(1);
+        }
+        if (setresuid(-1, realuid, realuid) != 0) {
+            perror("Could not drop setuid privileges");
+            exit(1);
+        }
+    }
+
+    snprintf(buf, sizeof(buf), "%s/Xorg.bin", SUID_WRAPPER_DIR);
+
+    /* Check if the server is executable by our real uid */
+    if (access(buf, X_OK) != 0) {
+        perror("Missing execute permissions for " SUID_WRAPPER_DIR "Xorg.bin");
+        exit(1);
+    }
+
+    argv[0] = buf;
+    (void) execv(argv[0], argv);
+    perror("Failed to execute " SUID_WRAPPER_DIR "/Xorg.bin");
+    exit(1);
+}
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 06455a8..f980a3d 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -288,9 +288,15 @@
 /* Support SHAPE extension */
 #undef SHAPE
 
+/* Where to install Xorg.bin and Xorg.wrap */
+#undef SUID_WRAPPER_DIR
+
 /* Define to 1 on systems derived from System V Release 4 */
 #undef SVR4
 
+/* sysconfdir */
+#undef SYSCONFDIR
+
 /* Support TCP socket connections */
 #undef TCPCONN
 
diff --git a/include/xwin-config.h.in b/include/xwin-config.h.in
index c5119f2..176c019 100644
--- a/include/xwin-config.h.in
+++ b/include/xwin-config.h.in
@@ -26,9 +26,6 @@
 /* Vendor web address for support */
 #undef __VENDORDWEBSUPPORT__
 
-/* Location of system.XWinrc */
-#undef SYSCONFDIR
-
 /* Default log location */
 #undef DEFAULT_LOGDIR
 
diff --git a/manpages.am b/manpages.am
index dfd6719..648210b 100644
--- a/manpages.am
+++ b/manpages.am
@@ -31,6 +31,7 @@ MAN_SUBSTS += 	-e 's|__logdir__|$(logdir)|g' \
 		-e 's|__XKB_DFLT_OPTIONS__|$(XKB_DFLT_OPTIONS)|g' \
 		-e 's|__bundle_id_prefix__|$(BUNDLE_ID_PREFIX)|g' \
 		-e 's|__modulepath__|$(DEFAULT_MODULE_PATH)|g' \
+		-e 's|__suid_wrapper_dir__|$(SUID_WRAPPER_DIR)|g' \
 		-e 's|__default_font_path__|$(COMPILEDDEFAULTFONTPATH)|g' \
 		-e '\|$(COMPILEDDEFAULTFONTPATH)| s|/,|/, |g'
 
commit d35a02a767017f13db4bd4742eef49293d5a30ea
Author: Rui Matos <tiagomatos at gmail.com>
Date:   Fri Mar 7 14:32:27 2014 -0800

    xkb: Repurpose XkbCopyDeviceKeymap to apply a given keymap to a device
    
    This will also make it useful for cases when we have a new keymap to
    apply to a device but don't have a source device.
    
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e9f670e..9c207eb 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -230,7 +230,7 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
 
     mk->sourceid = device->id;
 
-    if (!XkbCopyDeviceKeymap(master, device))
+    if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
         FatalError("Couldn't pivot keymap from device to core!\n");
 }
 
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 06f1200..c1c1561 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -824,8 +824,8 @@ extern _X_EXPORT void XkbSendNewKeyboardNotify(DeviceIntPtr /* kbd */ ,
 extern Bool XkbCopyKeymap(XkbDescPtr /* dst */ ,
                           XkbDescPtr /* src */ );
 
-extern _X_EXPORT Bool XkbCopyDeviceKeymap(DeviceIntPtr /* dst */ ,
-                                          DeviceIntPtr /* src */ );
+extern _X_EXPORT Bool XkbDeviceApplyKeymap(DeviceIntPtr /* dst */ ,
+                                           XkbDescPtr /* src */ );
 
 extern void XkbFilterEvents(ClientPtr /* pClient */ ,
                             int /* nEvents */ ,
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 920ec72..dc570f0 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5979,7 +5979,7 @@ ProcXkbGetKbdByName(ClientPtr client)
                 continue;
 
             if (tmpd != dev)
-                XkbCopyDeviceKeymap(tmpd, dev);
+                XkbDeviceApplyKeymap(tmpd, xkb);
 
             if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
                 old_sli = tmpd->kbdfeed->xkb_sli;
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index b59d925..6cf6e79 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -1999,28 +1999,28 @@ XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src)
 }
 
 Bool
-XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src)
+XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc)
 {
     xkbNewKeyboardNotify nkn;
     Bool ret;
 
-    if (!dst->key || !src->key)
+    if (!dst->key || !desc)
         return FALSE;
 
     memset(&nkn, 0, sizeof(xkbNewKeyboardNotify));
     nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code;
     nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code;
     nkn.deviceID = dst->id;
-    nkn.oldDeviceID = dst->id;  /* maybe src->id? */
-    nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code;
-    nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code;
+    nkn.oldDeviceID = dst->id;
+    nkn.minKeyCode = desc->min_key_code;
+    nkn.maxKeyCode = desc->max_key_code;
     nkn.requestMajor = XkbReqCode;
     nkn.requestMinor = X_kbSetMap;      /* Near enough's good enough. */
     nkn.changed = XkbNKN_KeycodesMask;
-    if (src->key->xkbInfo->desc->geom)
+    if (desc->geom)
         nkn.changed |= XkbNKN_GeometryMask;
 
-    ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc);
+    ret = XkbCopyKeymap(dst->key->xkbInfo->desc, desc);
     if (ret)
         XkbSendNewKeyboardNotify(dst, &nkn);
 
commit 361f405d3c866bc4d22ef84975fe771691156336
Author: Rui Matos <tiagomatos at gmail.com>
Date:   Fri Mar 7 14:32:28 2014 -0800

    xkb: Factor out a function to copy a keymap's controls onto another
    
    Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index f857b22..06f1200 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -841,6 +841,9 @@ extern void XkbFakeDeviceButton(DeviceIntPtr /* dev */ ,
                                 int /* press */ ,
                                 int /* button */ );
 
+extern _X_EXPORT void XkbCopyControls(XkbDescPtr /* dst */ ,
+                                      XkbDescPtr /* src */ );
+
 #include "xkbfile.h"
 #include "xkbrules.h"
 
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 31bb8d3..920ec72 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -5950,25 +5950,13 @@ ProcXkbGetKbdByName(ClientPtr client)
     if (rep.loaded) {
         XkbDescPtr old_xkb;
         xkbNewKeyboardNotify nkn;
-        int i, nG, nTG;
 
         old_xkb = xkb;
         xkb = new;
         dev->key->xkbInfo->desc = xkb;
         new = old_xkb;          /* so it'll get freed automatically */
 
-        *xkb->ctrls = *old_xkb->ctrls;
-        for (nG = nTG = 0, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
-            nG = XkbKeyNumGroups(xkb, i);
-            if (nG >= XkbNumKbdGroups) {
-                nTG = XkbNumKbdGroups;
-                break;
-            }
-            if (nG > nTG) {
-                nTG = nG;
-            }
-        }
-        xkb->ctrls->num_groups = nTG;
+        XkbCopyControls(xkb, old_xkb);
 
         nkn.deviceID = nkn.oldDeviceID = dev->id;
         nkn.minKeyCode = new->min_key_code;
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 6c6af60..b59d925 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -2090,3 +2090,26 @@ XkbMergeLockedPtrBtns(DeviceIntPtr master)
         xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
     }
 }
+
+void
+XkbCopyControls(XkbDescPtr dst, XkbDescPtr src)
+{
+    int i, nG, nTG;
+
+    if (!dst || !src)
+        return;
+
+    *dst->ctrls = *src->ctrls;
+
+    for (nG = nTG = 0, i = dst->min_key_code; i <= dst->max_key_code; i++) {
+        nG = XkbKeyNumGroups(dst, i);
+        if (nG >= XkbNumKbdGroups) {
+            nTG = XkbNumKbdGroups;
+            break;
+        }
+        if (nG > nTG) {
+            nTG = nG;
+        }
+    }
+    dst->ctrls->num_groups = nTG;
+}
commit 81a4952d3dcab9ca3a1ee399c773f5ac352036c4
Merge: 96a28e9 7950664
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 11 22:04:36 2014 -0700

    Merge remote-tracking branch 'whot/for-keith'

commit 795066477ee81b5b82e490eac8bed6b656d01f17
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 26 07:54:56 2014 +1000

    config: search for PnPID on all parents (#75513)
    
    The PnPID for a device may not be on the immediate parent, so search up the
    device tree until we find one.
    
    X.Org Bug 75513 <http://bugs.freedesktop.org/show_bug.cgi?id=75513>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Tested-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>

diff --git a/config/hal.c b/config/hal.c
index 94cb6e7..ea574ca 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -185,8 +185,7 @@ device_added(LibHalContext * hal_ctx, const char *udi)
     parent = get_prop_string(hal_ctx, udi, "info.parent");
     if (parent) {
         int usb_vendor, usb_product;
-
-        attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
+        char *old_parent;
 
         /* construct USB ID in lowercase - "0000:ffff" */
         usb_vendor = libhal_device_get_property_int(hal_ctx, parent,
@@ -204,7 +203,18 @@ device_added(LibHalContext * hal_ctx, const char *udi)
                 == -1)
                 attrs.usb_id = NULL;
 
-        free(parent);
+        attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
+        old_parent = parent;
+
+        while (!attrs.pnp_id &&
+               (parent = get_prop_string(hal_ctx, parent, "info.parent"))) {
+            attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
+
+            free(old_parent);
+            old_parent = parent;
+        }
+
+        free(old_parent);
     }
 
     input_options = input_option_new(NULL, "_source", "server/hal");
diff --git a/config/udev.c b/config/udev.c
index d70eeb4..d88abaa 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -149,10 +149,6 @@ device_added(struct udev_device *udev_device)
             LOG_PROPERTY(ppath, "NAME", name);
         }
 
-        if (pnp_id)
-            attrs.pnp_id = strdup(pnp_id);
-        LOG_SYSATTR(ppath, "id", pnp_id);
-
         /* construct USB ID in lowercase hex - "0000:ffff" */
         if (product &&
             sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) {
@@ -164,6 +160,17 @@ device_added(struct udev_device *udev_device)
                 LOG_PROPERTY(ppath, "PRODUCT", product);
             attrs.usb_id = usb_id;
         }
+
+        while (!pnp_id && (parent = udev_device_get_parent(parent))) {
+            pnp_id = udev_device_get_sysattr_value(parent, "id");
+            if (!pnp_id)
+                continue;
+
+            attrs.pnp_id = strdup(pnp_id);
+            ppath = udev_device_get_devnode(parent);
+            LOG_SYSATTR(ppath, "id", pnp_id);
+        }
+
     }
     if (!name)
         name = "(unnamed)";
commit 45fb3a934dc0db51584aba37c2f9d73deff9191d
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 26 16:20:08 2014 +1000

    xkb: push locked modifier state down to attached slave devices
    
    Whenever the master changes, push the locked modifier state to the attached
    slave devices, then update the indicators. This way, when NumLock or CapsLock
    are hit on any device, the LED will light up on all devices. Likewise, a new
    keyboard attached to a master device will light up with the correct
    indicators.
    
    The indicators are handled per-keyboard, depending on the layout, i.e. if one
    keyboard has grp_led:num set, the NumLock LED won't light up on that keyboard.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/dix/devices.c b/dix/devices.c
index 1c86d52..ab923d5 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -416,6 +416,8 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent)
         XISendDeviceHierarchyEvent(flags);
     }
 
+    if (!IsMaster(dev))
+        XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
     RecalculateMasterButtons(dev);
 
     /* initialise an idle timer for this device*/
@@ -2649,6 +2651,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         dev->spriteInfo->paired = master;
         dev->spriteInfo->spriteOwner = FALSE;
 
+        XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
         RecalculateMasterButtons(master);
     }
 
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index e799799..f857b22 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -638,6 +638,10 @@ extern _X_EXPORT void XkbHandleActions(DeviceIntPtr /* dev */ ,
                                        DeviceEvent *    /* event */
     );
 
+extern void XkbPushLockedStateToSlaves(DeviceIntPtr /* master */,
+                                       int /* evtype */,
+                                       int /* key */);
+
 extern _X_EXPORT Bool XkbEnableDisableControls(XkbSrvInfoPtr /* xkbi */ ,
                                                unsigned long /* change */ ,
                                                unsigned long /* newValues */ ,
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 7e5512c..c44f44b 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1174,6 +1174,25 @@ _XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key)
 }
 
 void
+XkbPushLockedStateToSlaves(DeviceIntPtr master, int evtype, int key)
+{
+    DeviceIntPtr dev;
+    Bool genStateNotify;
+
+    nt_list_for_each_entry(dev, inputInfo.devices, next) {
+        if (!dev->key || GetMaster(dev, MASTER_KEYBOARD) != master)
+            continue;
+
+        genStateNotify = _XkbEnsureStateChange(dev->key->xkbInfo);
+
+        dev->key->xkbInfo->state.locked_mods =
+            master->key->xkbInfo->state.locked_mods;
+
+        _XkbApplyState(dev, genStateNotify, evtype, key);
+    }
+}
+
+void
 XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
 {
     int key, bit, i;
@@ -1327,6 +1346,7 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
     }
 
     _XkbApplyState(dev, genStateNotify, event->type, key);
+    XkbPushLockedStateToSlaves(dev, event->type, key);
 }
 
 int
commit 656841798c99bcd79da47c03ec666a48b855541f
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 26 16:16:10 2014 +1000

    xkb: factor out state update into a function
    
    No functional changes
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 3da57f7..7e5512c 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1143,13 +1143,43 @@ _XkbEnsureStateChange(XkbSrvInfoPtr xkbi)
     return genStateNotify;
 }
 
+static void
+_XkbApplyState(DeviceIntPtr dev, Bool genStateNotify, int evtype, int key)
+{
+    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+    int changed;
+
+    XkbComputeDerivedState(xkbi);
+
+    changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state);
+    if (genStateNotify) {
+        if (changed) {
+            xkbStateNotify sn;
+
+            sn.keycode = key;
+            sn.eventType = evtype;
+            sn.requestMajor = sn.requestMinor = 0;
+            sn.changed = changed;
+            XkbSendStateNotify(dev, &sn);
+        }
+        xkbi->flags &= ~_XkbStateNotifyInProgress;
+    }
+
+    changed = XkbIndicatorsToUpdate(dev, changed, FALSE);
+    if (changed) {
+        XkbEventCauseRec cause;
+        XkbSetCauseKey(&cause, key, evtype);
+        XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause);
+    }
+}
+
 void
 XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
 {
     int key, bit, i;
     XkbSrvInfoPtr xkbi;
     KeyClassPtr keyc;
-    int changed, sendEvent;
+    int sendEvent;
     Bool genStateNotify;
     XkbAction act;
     XkbFilterPtr filter;
@@ -1296,28 +1326,7 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
         FixKeyState(event, dev);
     }
 
-    XkbComputeDerivedState(xkbi);
-    changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state);
-    if (genStateNotify) {
-        if (changed) {
-            xkbStateNotify sn;
-
-            sn.keycode = key;
-            sn.eventType = event->type;
-            sn.requestMajor = sn.requestMinor = 0;
-            sn.changed = changed;
-            XkbSendStateNotify(dev, &sn);
-        }
-        xkbi->flags &= ~_XkbStateNotifyInProgress;
-    }
-    changed = XkbIndicatorsToUpdate(dev, changed, FALSE);
-    if (changed) {
-        XkbEventCauseRec cause;
-
-        XkbSetCauseKey(&cause, key, event->type);
-        XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause);
-    }
-    return;
+    _XkbApplyState(dev, genStateNotify, event->type, key);
 }
 
 int
commit dda2468e579762dbd1fed2c75b5587d98f841e9c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 26 16:03:19 2014 +1000

    xkb: factor out the StateNotify flag check
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Daniel Stone <daniel at fooishbar.org>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 1443498..3da57f7 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1127,6 +1127,22 @@ _XkbApplyFilters(XkbSrvInfoPtr xkbi, unsigned kc, XkbAction *pAction)
     return send;
 }
 
+static int
+_XkbEnsureStateChange(XkbSrvInfoPtr xkbi)
+{
+    Bool genStateNotify = FALSE;
+
+    /* The state may change, so if we're not in the middle of sending a state
+     * notify, prepare for it */
+    if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) {
+        xkbi->prev_state = xkbi->state;
+        xkbi->flags |= _XkbStateNotifyInProgress;
+        genStateNotify = TRUE;
+    }
+
+    return genStateNotify;
+}
+
 void
 XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
 {
@@ -1146,15 +1162,8 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
     keyc = kbd->key;
     xkbi = keyc->xkbInfo;
     key = event->detail.key;
-    /* The state may change, so if we're not in the middle of sending a state
-     * notify, prepare for it */
-    if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) {
-        xkbi->prev_state = xkbi->state;
-        xkbi->flags |= _XkbStateNotifyInProgress;
-        genStateNotify = TRUE;
-    }
-    else
-        genStateNotify = FALSE;
+
+    genStateNotify = _XkbEnsureStateChange(xkbi);
 
     xkbi->clearMods = xkbi->setMods = 0;
     xkbi->groupChange = 0;
commit fdb4ec86c29d85c1f68418a26e64bcc05b9c14ae
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Mar 11 14:21:27 2014 +1000

    xfree86: handle xorg.conf devices with logind
    
    Only devices from the config backend have their attributes set, devices from
    the xorg.conf only have Option "Device". That option is also set by the
    config backend, so use it.
    
    And since the config backend sets our major/minor but xorg.conf devices don't
    have that set, make sure we try to stat it first where needed.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 7c3e479..36b92a9 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -81,6 +81,7 @@
 
 #include <stdarg.h>
 #include <stdint.h>             /* for int64_t */
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include "mi.h"
@@ -804,6 +805,18 @@ xf86InputDevicePostInit(DeviceIntPtr dev)
     return Success;
 }
 
+static void
+xf86stat(const char *path, int *maj, int *min)
+{
+    struct stat st;
+
+    if (stat(path, &st) == -1)
+        return;
+
+    *maj = major(st.st_rdev);
+    *min = minor(st.st_rdev);
+}
+
 /**
  * Create a new input device, activate and enable it.
  *
@@ -828,6 +841,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
     DeviceIntPtr dev = NULL;
     Bool paused;
     int rval;
+    const char *path;
 
     /* Memory leak for every attached device if we don't
      * test if the module is already loaded first */
@@ -841,9 +855,13 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
         goto unwind;
     }
 
-    if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
+    path = xf86CheckStrOption(pInfo->options, "Device", NULL);
+    if (path && pInfo->major == 0 && pInfo->minor == 0)
+        xf86stat(path, &pInfo->major, &pInfo->minor);
+
+    if (path && (drv->capabilities & XI86_DRV_CAP_SERVER_FD)){
         int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
-                                        pInfo->attrs->device, &paused);
+                                        path, &paused);
         if (fd != -1) {
             if (paused) {
                 /* Put on new_input_devices list for delayed probe */
commit 4754af9ddbd55c5637b56bd9f37d0d3414c839a8
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Mar 11 14:20:51 2014 +1000

    config: only free odev->attrib_name for string types
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/config/config.c b/config/config.c
index 7971b87..4ad7330 100644
--- a/config/config.c
+++ b/config/config.c
@@ -246,7 +246,8 @@ config_odev_free_attributes(struct OdevAttributes *attribs)
         case ODEV_ATTRIB_FD: fd = iter->attrib_value; break;
         }
         xorg_list_del(&iter->member);
-        free(iter->attrib_name);
+        if (iter->attrib_type == ODEV_ATTRIB_STRING)
+            free(iter->attrib_name);
         free(iter);
     }
 
commit 96a28e9c914d7ae9b269f73a27b99cbd3c465ac8
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 18:50:07 2014 -0800

    glx: Clear new FBConfig attributes to 0 by default.
    
    The visualSelectGroup wasn't getting set (since our DRI drivers don't
    use it), and and since it's the top priority in the sort order, you
    got random sorting of your visuals unless malloc really returned you
    new memory.  This manifested as Xephyr -glamor rendering to a
    multisampled window on my system, which as you might guess was
    slightly lower performance than expected.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/glx/glxdricommon.c b/glx/glxdricommon.c
index 69d4b29..62cce13 100644
--- a/glx/glxdricommon.c
+++ b/glx/glxdricommon.c
@@ -132,7 +132,7 @@ createModeFromConfig(const __DRIcoreExtension * core,
     unsigned int attrib, value;
     int i;
 
-    config = malloc(sizeof *config);
+    config = calloc(1, sizeof *config);
 
     config->driConfig = driConfig;
 
commit 2843a2f9b58a4aae2949111722c5c1bf3878674b
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Feb 25 16:56:54 2014 -0800

    glamor: Use buffer_storage
    
    v2:
      - Make the default buffer size a #define. (by Markus Wick)
      - Fix the return offset for mapping with buffer_storage.  (oops!)
    v3:
      - Avoid GL error at first rendering from unmapping no buffer.
      - Rebase on the glBindBuffer(GL_ARRAY_BUFFER, 0) change.
    v4: Rebase on Markus's vbo init changes.
    v5: Fix missing put_context() in the buffer_storage fallback path.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index dc69c72..e856179 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -353,6 +353,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         glamor_gl_has_extension("GL_MESA_pack_invert");
     glamor_priv->has_fbo_blit =
         glamor_gl_has_extension("GL_EXT_framebuffer_blit");
+    glamor_priv->has_buffer_storage =
+        glamor_gl_has_extension("GL_ARB_buffer_storage");
     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
 #ifdef MAX_FBO_SIZE
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 986e729..d15eabd 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -208,6 +208,7 @@ typedef struct glamor_screen_private {
     enum glamor_gl_flavor gl_flavor;
     int has_pack_invert;
     int has_fbo_blit;
+    int has_buffer_storage;
     int max_fbo_size;
 
     struct xorg_list
diff --git a/glamor/glamor_vbo.c b/glamor/glamor_vbo.c
index 78c9033..5e98bfe 100644
--- a/glamor/glamor_vbo.c
+++ b/glamor/glamor_vbo.c
@@ -52,7 +52,51 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
 
     glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
 
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+    if (glamor_priv->has_buffer_storage) {
+        if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
+            if (glamor_priv->vbo_size)
+                glUnmapBuffer(GL_ARRAY_BUFFER);
+
+            if (size > glamor_priv->vbo_size) {
+                glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
+
+                /* We aren't allowed to resize glBufferStorage()
+                 * buffers, so we need to gen a new one.
+                 */
+                glDeleteBuffers(1, &glamor_priv->vbo);
+                glGenBuffers(1, &glamor_priv->vbo);
+                glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+
+                assert(glGetError() == GL_NO_ERROR);
+                glBufferStorage(GL_ARRAY_BUFFER, glamor_priv->vbo_size, NULL,
+                                GL_MAP_WRITE_BIT |
+                                GL_MAP_PERSISTENT_BIT |
+                                GL_MAP_COHERENT_BIT);
+
+                if (glGetError() != GL_NO_ERROR) {
+                    /* If the driver failed our coherent mapping, fall
+                     * back to the ARB_mbr path.
+                     */
+                    glamor_priv->has_buffer_storage = false;
+                    glamor_priv->vbo_size = 0;
+                    glamor_put_context(glamor_priv);
+
+                    return glamor_get_vbo_space(screen, size, vbo_offset);
+                }
+            }
+
+            glamor_priv->vbo_offset = 0;
+            glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
+                                               0, glamor_priv->vbo_size,
+                                               GL_MAP_WRITE_BIT |
+                                               GL_MAP_INVALIDATE_BUFFER_BIT |
+                                               GL_MAP_PERSISTENT_BIT |
+                                               GL_MAP_COHERENT_BIT);
+        }
+        *vbo_offset = (void *)(uintptr_t)glamor_priv->vbo_offset;
+        data = glamor_priv->vb + glamor_priv->vbo_offset;
+        glamor_priv->vbo_offset += size;
+    } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
             glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
             glamor_priv->vbo_offset = 0;
@@ -98,7 +142,12 @@ glamor_put_vbo_space(ScreenPtr screen)
 
     glamor_get_context(glamor_priv);
 
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+    if (glamor_priv->has_buffer_storage) {
+        /* If we're in the ARB_buffer_storage path, we have a
+         * persistent mapping, so we can leave it around until we
+         * reach the end of the buffer.
+         */
+    } else if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         glUnmapBuffer(GL_ARRAY_BUFFER);
     } else {
         glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
commit 9b86f7a1ab7904fbbe04283b6461a31470c77972
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Jan 12 07:54:51 2014 -0800

    glamor: Fix requested composite VBO size.
    
    The argument to setup_composte_vbo is the number of verts.
    
    v2: Drop the now-unused vert_stride value.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 7829977..086526d 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1189,7 +1189,6 @@ glamor_composite_with_shader(CARD8 op,
     PictFormatShort saved_source_format = 0;
     float src_matrix[9], mask_matrix[9];
     float *psrc_matrix = NULL, *pmask_matrix = NULL;
-    int vert_stride = 4;
     int nrect_max;
     Bool ret = FALSE;
     glamor_composite_shader *shader = NULL, *shader_ca = NULL;
@@ -1238,7 +1237,6 @@ glamor_composite_with_shader(CARD8 op,
             psrc_matrix = src_matrix;
             glamor_picture_get_matrixf(source, psrc_matrix);
         }
-        vert_stride += 4;
     }
 
     if (glamor_priv->has_mask_coords) {
@@ -1250,11 +1248,9 @@ glamor_composite_with_shader(CARD8 op,
             pmask_matrix = mask_matrix;
             glamor_picture_get_matrixf(mask, pmask_matrix);
         }
-        vert_stride += 4;
     }
 
-    nrect_max = (vert_stride * nrect) > GLAMOR_COMPOSITE_VBO_VERT_CNT ?
-        (GLAMOR_COMPOSITE_VBO_VERT_CNT / vert_stride) : nrect;
+    nrect_max = MIN(nrect, GLAMOR_COMPOSITE_VBO_VERT_CNT / 4);
 
     while (nrect) {
         int mrect, rect_processed;
@@ -1262,7 +1258,7 @@ glamor_composite_with_shader(CARD8 op,
         float *vertices;
 
         mrect = nrect > nrect_max ? nrect_max : nrect;
-        vertices = glamor_setup_composite_vbo(screen, mrect * vert_stride);
+        vertices = glamor_setup_composite_vbo(screen, mrect * 4);
         rect_processed = mrect;
         vb_stride = glamor_priv->vb_stride / sizeof(float);
         while (mrect--) {
commit d310d566b18e55bce27301e9ac78a7894d5194dd
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 6 09:29:57 2014 +0800

    glamor: Extract the streamed vertex data code used by Render.
    
    We should be uploading any vertex data using this kind of upload
    style, since it saves a bunch of extra copies of our vertex data.
    
    v2:
      - Add a simple comment about what the function does.
      - Use get_vbo_space()'s return in trapezoids, instead of dereffing
        glamor_priv->vb (by Markus Wick).
      - Fix the double-unmapping by moving put_vbo_space() outside of
        flush_composite_rects().
      - Remove the rest of the composite_vbo_offset usage, and just always
        use get_vbo_space()'s return value.
    v3:
      - Fix failure to put_vbo_space in traps when no prims were
        generated.
      - Unbind the VBO from put_vbo_space().  Keeps callers from
        forgetting to do so.
    v4:
      - Split out some changes into the previous 3 commits while trying to
        track down a regression.
      - Fix regression due to rebase fail where glamor_priv->vbo_offset
        wasn't incremented.
    v5:
      - Fix GLES2 VBO sizing.
      - Add a comment about resize behavior.
      - Move glamor_vbo.c init code to glamor_vbo.c from
        glamor_render.c. (Derived from Markus's changes, but the GLES2 fix
        dropped almost all of the code in the functions).
    v6:
      - Drop the initial BufferData on GLES2 (it happens at put() time).
      - Don't forget to set vbo_offset to the size on GLES2.
      - Use char * instead of void * in the cast to return the vbo_offset.
      - Resize the default FBO to 512kb, to be similar to previous
        behavior.  +1.66124% +/- 0.284223% (n=679) on aa10text.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 77492bc..ffc8c23 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -34,6 +34,7 @@ libglamor_la_SOURCES = \
 	glamor_pixmap.c\
 	glamor_largepixmap.c\
 	glamor_picture.c\
+	glamor_vbo.c \
 	glamor_window.c\
 	glamor_fbo.c\
 	glamor_compositerects.c\
diff --git a/glamor/glamor.c b/glamor/glamor.c
index fe9f761..dc69c72 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -439,6 +439,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     ps->DestroyPicture = glamor_destroy_picture;
     glamor_init_composite_shaders(screen);
 #endif
+    glamor_init_vbo(screen);
     glamor_init_pixmap_fbo(screen);
     glamor_init_solid_shader(screen);
     glamor_init_tile_shader(screen);
@@ -478,6 +479,7 @@ glamor_release_screen_priv(ScreenPtr screen)
 #ifdef RENDER
     glamor_fini_composite_shaders(screen);
 #endif
+    glamor_fini_vbo(screen);
     glamor_fini_pixmap_fbo(screen);
     glamor_fini_solid_shader(screen);
     glamor_fini_tile_shader(screen);
diff --git a/glamor/glamor.h b/glamor/glamor.h
index e12f497..e25dc73 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -324,6 +324,7 @@ extern _X_EXPORT int glamor_create_gc(GCPtr gc);
 
 extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes,
                                          DrawablePtr drawable);
+
 /* Glamor rendering/drawing functions with XXX_nf.
  * nf means no fallback within glamor internal if possible. If glamor
  * fail to accelerate the operation, glamor will return a false, and the
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index b23c12b..986e729 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -220,8 +220,15 @@ typedef struct glamor_screen_private {
 
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
+    /** Next offset within the VBO that glamor_get_vbo_space() will use. */
     int vbo_offset;
     int vbo_size;
+    /**
+     * Pointer to glamor_get_vbo_space()'s current VBO mapping.
+     *
+     * Note that this is not necessarily equal to the pointer returned
+     * by glamor_get_vbo_space(), so it can't be used in place of that.
+     */
     char *vb;
     int vb_stride;
     Bool has_source_coords, has_mask_coords;
@@ -744,6 +751,17 @@ void glamor_triangles(CARD8 op,
 void glamor_pixmap_init(ScreenPtr screen);
 void glamor_pixmap_fini(ScreenPtr screen);
 
+/* glamor_vbo.c */
+
+void glamor_init_vbo(ScreenPtr screen);
+void glamor_fini_vbo(ScreenPtr screen);
+
+void *
+glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset);
+
+void
+glamor_put_vbo_space(ScreenPtr screen);
+
 /** 
  * Download a pixmap's texture to cpu memory. If success,
  * One copy of current pixmap's texture will be put into
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 69a22d9..7829977 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -403,12 +403,10 @@ glamor_init_composite_shaders(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
     unsigned short *eb;
-    float *vb = NULL;
     int eb_size;
 
     glamor_priv = glamor_get_screen_private(screen);
     glamor_get_context(glamor_priv);
-    glGenBuffers(1, &glamor_priv->vbo);
     glGenBuffers(1, &glamor_priv->ebo);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
@@ -419,9 +417,6 @@ glamor_init_composite_shaders(ScreenPtr screen)
         eb = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
     }
     else {
-        vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2);
-        if (vb == NULL)
-            FatalError("Failed to allocate vb memory.\n");
         eb = malloc(eb_size);
     }
 
@@ -438,14 +433,7 @@ glamor_init_composite_shaders(ScreenPtr screen)
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        glBufferData(GL_ARRAY_BUFFER,
-                     GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) *
-                     2, NULL, GL_DYNAMIC_DRAW);
-        glBindBuffer(GL_ARRAY_BUFFER, 0);
-
         free(eb);
-        glamor_priv->vb = (char *) vb;
     }
 
     glamor_put_context(glamor_priv);
@@ -460,7 +448,6 @@ glamor_fini_composite_shaders(ScreenPtr screen)
 
     glamor_priv = glamor_get_screen_private(screen);
     glamor_get_context(glamor_priv);
-    glDeleteBuffers(1, &glamor_priv->vbo);
     glDeleteBuffers(1, &glamor_priv->ebo);
 
     for (i = 0; i < SHADER_SOURCE_COUNT; i++)
@@ -470,8 +457,6 @@ glamor_fini_composite_shaders(ScreenPtr screen)
                 if (shader->prog)
                     glDeleteProgram(shader->prog);
             }
-    if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb)
-        free(glamor_priv->vb);
 
     glamor_put_context(glamor_priv);
 }
@@ -706,6 +691,8 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     int vert_size;
+    char *vbo_offset;
+    float *vb;
 
     glamor_priv->render_nr_verts = 0;
     glamor_priv->vb_stride = 2 * sizeof(float);
@@ -717,56 +704,32 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
     vert_size = n_verts * glamor_priv->vb_stride;
 
     glamor_get_context(glamor_priv);
-    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
-            glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT *
-                glamor_priv->vb_stride;
-            glamor_priv->vbo_offset = 0;
-            glBufferData(GL_ARRAY_BUFFER,
-                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
-        }
-
-        glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
-                                           glamor_priv->vbo_offset,
-                                           vert_size,
-                                           GL_MAP_WRITE_BIT |
-                                           GL_MAP_UNSYNCHRONIZED_BIT |
-                                           GL_MAP_INVALIDATE_RANGE_BIT);
-        assert(glamor_priv->vb != NULL);
-        glamor_priv->vb -= glamor_priv->vbo_offset;
-    }
-    else
-        glamor_priv->vbo_offset = 0;
+    vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
-                          glamor_priv->vb_stride,
-                          (void *) ((long)
-                                    glamor_priv->vbo_offset));
+                          glamor_priv->vb_stride, vbo_offset);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     if (glamor_priv->has_source_coords) {
         glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
                               GL_FLOAT, GL_FALSE,
                               glamor_priv->vb_stride,
-                              (void *) ((long) glamor_priv->vbo_offset +
-                                        2 * sizeof(float)));
+                              vbo_offset + 2 * sizeof(float));
         glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     }
 
     if (glamor_priv->has_mask_coords) {
         glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE,
                               glamor_priv->vb_stride,
-                              (void *) ((long) glamor_priv->vbo_offset +
-                                        (glamor_priv->has_source_coords ?
-                                         4 : 2) * sizeof(float)));
+                              vbo_offset + (glamor_priv->has_source_coords ?
+                                            4 : 2) * sizeof(float));
         glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
     }
     glamor_put_context(glamor_priv);
 
-    return glamor_priv->vb + glamor_priv->vbo_offset;
+    return vb;
 }
 
 static void
@@ -775,14 +738,6 @@ glamor_flush_composite_rects(ScreenPtr screen)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     glamor_get_context(glamor_priv);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-    else {
-
-        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
-                     glamor_priv->vb, GL_DYNAMIC_DRAW);
-    }
 
     if (!glamor_priv->render_nr_verts)
         return;
@@ -1334,8 +1289,6 @@ glamor_composite_with_shader(CARD8 op,
                  x_dest, y_dest, x_source, y_source, x_mask, y_mask, width,
                  height);
 
-            assert(glamor_priv->vbo_offset <
-                   glamor_priv->vbo_size - glamor_priv->vb_stride);
             glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale,
                                              dst_yscale, x_dest, y_dest,
                                              x_dest + width, y_dest + height,
@@ -1366,12 +1319,12 @@ glamor_composite_with_shader(CARD8 op,
                 vertices += 2;
             }
             glamor_priv->render_nr_verts += 4;
-            glamor_priv->vbo_offset += glamor_priv->vb_stride * 4;
             rects++;
 
             /* We've incremented by one of our 4 verts, now do the other 3. */
             vertices += 3 * vb_stride;
         }
+        glamor_put_vbo_space(screen);
         glamor_flush_composite_rects(screen);
         nrect -= rect_processed;
         if (two_pass_ca) {
@@ -1384,7 +1337,6 @@ glamor_composite_with_shader(CARD8 op,
         }
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 53821b1..0064f2a 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -213,7 +213,6 @@ glamor_emit_composite_vert(ScreenPtr screen,
     }
 
     glamor_priv->render_nr_verts++;
-    glamor_priv->vbo_offset += glamor_priv->vb_stride;
 }
 
 static void
@@ -237,14 +236,7 @@ glamor_flush_composite_triangles(ScreenPtr screen)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     glamor_get_context(glamor_priv);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        glUnmapBuffer(GL_ARRAY_BUFFER);
-    else {
-
-        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
-                     glamor_priv->vb, GL_DYNAMIC_DRAW);
-    }
+    glamor_put_vbo_space(screen);
 
     if (!glamor_priv->render_nr_verts)
         return;
@@ -613,6 +605,8 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     int stride;
     int vert_size;
+    char *vbo_offset;
+    void *vb;
 
     glamor_priv->render_nr_verts = 0;
 
@@ -641,68 +635,43 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
     glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
-    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
-            glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT *
-                glamor_priv->vb_stride;
-            glamor_priv->vbo_offset = 0;
-            glBufferData(GL_ARRAY_BUFFER,
-                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
-        }
-
-        glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
-                                                     glamor_priv->vbo_offset,
-                                                     vert_size,
-                                                     GL_MAP_WRITE_BIT |
-                                                     GL_MAP_UNSYNCHRONIZED_BIT);
-
-        assert(glamor_priv->vb != NULL);
-        glamor_priv->vb -= glamor_priv->vbo_offset;
-    }
-    else {
-        glamor_priv->vbo_offset = 0;
-    }
+    vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     /* Set the vertex pointer. */
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, glamor_priv->vb_stride,
-                          (void *) ((long) glamor_priv->vbo_offset));
+                          vbo_offset);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     stride = 2;
 
     glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
                           GL_FALSE, glamor_priv->vb_stride,
-                          (void *) ((long) glamor_priv->vbo_offset +
-                                    stride * sizeof(float)));
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     stride += 2;
 
     glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
+                          GL_FALSE, glamor_priv->vb_stride,
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
     stride += 2;
 
     glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
+                          GL_FALSE, glamor_priv->vb_stride,
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     stride += 4;
 
     glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
+                          GL_FALSE, glamor_priv->vb_stride,
+                          vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
     glamor_put_context(glamor_priv);
 
-    return glamor_priv->vb + glamor_priv->vbo_offset;
+    return vb;
 }
 
 static Bool
@@ -1008,7 +977,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     ret = TRUE;
 
  TRAPEZOID_RESET_GL:
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -1450,7 +1418,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
 
     pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale));
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     /* Now draw the Trapezoid mask. */
@@ -1575,25 +1542,17 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
                    ((float) ptrap->right.p1.y) / 65536, right_slope);
 
             glamor_priv->render_nr_verts += 4;
-            glamor_priv->vbo_offset += glamor_priv->vb_stride * 4;
-
             vertices += 3 * stride;
         }
 
         i += mrect;
 
+        glamor_put_vbo_space(screen);
+
         /* Now rendering. */
         if (!glamor_priv->render_nr_verts)
             continue;
 
-        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-            glUnmapBuffer(GL_ARRAY_BUFFER);
-        else {
-            glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-            glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
-                         glamor_priv->vb, GL_DYNAMIC_DRAW);
-        }
-
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
             glDrawRangeElements(GL_TRIANGLES, 0,
                                 glamor_priv->render_nr_verts,
@@ -1606,7 +1565,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
         }
     }
 
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glBlendFunc(GL_ONE, GL_ZERO);
     glDisable(GL_BLEND);
diff --git a/glamor/glamor_vbo.c b/glamor/glamor_vbo.c
new file mode 100644
index 0000000..78c9033
--- /dev/null
+++ b/glamor/glamor_vbo.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+/**
+ * @file glamor_vbo.c
+ *
+ * Helpers for managing streamed vertex bufffers used in glamor.
+ */
+
+#include "glamor_priv.h"
+
+/** Default size of the VBO, in bytes.
+ *
+ * If a single request is larger than this size, we'll resize the VBO
+ * and return an appropriate mapping, but we'll resize back down after
+ * that to avoid hogging that memory forever.  We don't anticipate
+ * normal usage actually requiring larger VBO sizes.
+ */
+#define GLAMOR_VBO_SIZE (512 * 1024)
+
+/**
+ * Returns a pointer to @size bytes of VBO storage, which should be
+ * accessed by the GL using vbo_offset within the VBO.
+ */
+void *
+glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    void *data;
+
+    glamor_get_context(glamor_priv);
+
+    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        if (glamor_priv->vbo_size < glamor_priv->vbo_offset + size) {
+            glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
+            glamor_priv->vbo_offset = 0;
+            glBufferData(GL_ARRAY_BUFFER,
+                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
+        }
+
+        data = glMapBufferRange(GL_ARRAY_BUFFER,
+                                glamor_priv->vbo_offset,
+                                size,
+                                GL_MAP_WRITE_BIT |
+                                GL_MAP_UNSYNCHRONIZED_BIT |
+                                GL_MAP_INVALIDATE_RANGE_BIT);
+        assert(data != NULL);
+        *vbo_offset = (char *)(uintptr_t)glamor_priv->vbo_offset;
+        glamor_priv->vbo_offset += size;
+    } else {
+        /* Return a pointer to the statically allocated non-VBO
+         * memory. We'll upload it through glBufferData() later.
+         */
+        if (glamor_priv->vbo_size < size) {
+            glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
+            free(glamor_priv->vb);
+            glamor_priv->vb = XNFalloc(size);
+        }
+        *vbo_offset = NULL;
+        /* We point to the start of glamor_priv->vb every time, and
+         * the vbo_offset determines the size of the glBufferData().
+         */
+        glamor_priv->vbo_offset = size;
+        data = glamor_priv->vb;
+    }
+
+    glamor_put_context(glamor_priv);
+
+    return data;
+}
+
+void
+glamor_put_vbo_space(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        glUnmapBuffer(GL_ARRAY_BUFFER);
+    } else {
+        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
+                     glamor_priv->vb, GL_DYNAMIC_DRAW);
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+    glamor_put_context(glamor_priv);
+}
+
+void
+glamor_init_vbo(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
+    glGenBuffers(1, &glamor_priv->vbo);
+
+    glamor_put_context(glamor_priv);
+}
+
+void
+glamor_fini_vbo(ScreenPtr screen)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
+    glDeleteBuffers(1, &glamor_priv->vbo);
+    if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP)
+        free(glamor_priv->vb);
+
+    glamor_put_context(glamor_priv);
+}
commit ffc8423077d8b5af36ab59f59e4e18109586aec9
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 17:05:31 2014 -0800

    glamor: Track the next vertex offset as we go for AA traps.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index b4a430a..53821b1 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -607,7 +607,7 @@ _glamor_clip_trapezoid_vertex(xTrapezoid *trap, BoxPtr pbox,
     return TRUE;
 }
 
-static void
+static void *
 glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -701,6 +701,8 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
     glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
     glamor_put_context(glamor_priv);
+
+    return glamor_priv->vb + glamor_priv->vbo_offset;
 }
 
 static Bool
@@ -1420,7 +1422,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
     BoxRec one_trap_bound;
     int nrect_max;
     int i, j;
-    float *vertices;
     float params[4];
 
     glamor_priv = glamor_get_screen_private(screen);
@@ -1461,11 +1462,12 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
     nrect_max = GLAMOR_COMPOSITE_VBO_VERT_CNT / (4 * GLAMOR_VERTEX_RIGHT_PARAM);
 
     for (i = 0; i < ntrap;) {
+        float *vertices;
         int mrect;
         int stride;
 
         mrect = (ntrap - i) > nrect_max ? nrect_max : (ntrap - i);
-        glamor_setup_composite_vbo_for_trapezoid(screen, 4 * mrect);
+        vertices = glamor_setup_composite_vbo_for_trapezoid(screen, 4 * mrect);
         stride = glamor_priv->vb_stride / sizeof(float);
 
         for (j = 0; j < mrect; j++) {
@@ -1488,8 +1490,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
 
             miTrapezoidBounds(1, ptrap, &one_trap_bound);
 
-            vertices =
-                (float *) (glamor_priv->vb + glamor_priv->vbo_offset) + 2;
+            vertices += 2;
             glamor_set_tcoords_ext((pixmap_priv->base.pixmap->drawable.width),
                                    (pixmap_priv->base.pixmap->drawable.height),
                                    (one_trap_bound.x1), (one_trap_bound.y1),
@@ -1561,6 +1562,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
             }
             params[2] = right_slope;
             glamor_set_const_ext(params, 4, vertices, 4, stride);
+            vertices += 4;
 
             DEBUGF("trap_top = %f, trap_bottom = %f, "
                    "trap_left_x = %f, trap_left_y = %f, left_slope = %f, "
@@ -1574,6 +1576,8 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
 
             glamor_priv->render_nr_verts += 4;
             glamor_priv->vbo_offset += glamor_priv->vb_stride * 4;
+
+            vertices += 3 * stride;
         }
 
         i += mrect;
commit ca307fd18d4dfded04979903737ec5dd03487625
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 17:03:14 2014 -0800

    glamor: Track the next vertex offset as we go for non-AA traps.
    
    v2: Use sizeof(float) instead of 4.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 7bbee4b..b4a430a 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -191,14 +191,16 @@ point_inside_trapezoid(int point[2], xTrapezoid *trap, xFixed cut_y)
 
 static void
 glamor_emit_composite_vert(ScreenPtr screen,
+                           float *vb,
                            const float *src_coords,
                            const float *mask_coords,
                            const float *dst_coords, int i)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    float *vb = (float *) (glamor_priv->vb + glamor_priv->vbo_offset);
     int j = 0;
 
+    vb += i * glamor_priv->vb_stride / sizeof(float);
+
     vb[j++] = dst_coords[i * 2 + 0];
     vb[j++] = dst_coords[i * 2 + 1];
     if (glamor_priv->has_source_coords) {
@@ -216,13 +218,17 @@ glamor_emit_composite_vert(ScreenPtr screen,
 
 static void
 glamor_emit_composite_triangle(ScreenPtr screen,
+                               float *vb,
                                const float *src_coords,
                                const float *mask_coords,
                                const float *dst_coords)
 {
-    glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 0);
-    glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 1);
-    glamor_emit_composite_vert(screen, src_coords, mask_coords, dst_coords, 2);
+    glamor_emit_composite_vert(screen, vb,
+                               src_coords, mask_coords, dst_coords, 0);
+    glamor_emit_composite_vert(screen, vb,
+                               src_coords, mask_coords, dst_coords, 1);
+    glamor_emit_composite_vert(screen, vb,
+                               src_coords, mask_coords, dst_coords, 2);
 }
 
 static void
@@ -887,6 +893,8 @@ _glamor_trapezoids_with_shader(CARD8 op,
 
     nclip_rect = nbox;
     while (nclip_rect) {
+        float *vb;
+
         mclip_rect = (nclip_rect * ntrap * 4) > ntriangle_per_loop ?
             (ntriangle_per_loop / (4 * ntrap)) : nclip_rect;
 
@@ -904,8 +912,9 @@ _glamor_trapezoids_with_shader(CARD8 op,
 
  NTRAPS_LOOP_AGAIN:
 
-        glamor_setup_composite_vbo(screen,
-                                   mclip_rect * traps_count * 4 * vert_stride);
+        vb = glamor_setup_composite_vbo(screen,
+                                        (mclip_rect * traps_count *
+                                         4 * vert_stride));
         clip_processed = mclip_rect;
 
         while (mclip_rect--) {
@@ -963,8 +972,10 @@ _glamor_trapezoids_with_shader(CARD8 op,
                                    source_texcoords[4], source_texcoords[5]);
                         }
 
-                        glamor_emit_composite_triangle(screen, source_texcoords,
+                        glamor_emit_composite_triangle(screen, vb,
+                                                       source_texcoords,
                                                        NULL, vertices);
+                        vb += 3 * glamor_priv->vb_stride / sizeof(float);
                     }
                 }
 
commit 03a33048a74d986e27668a4d01861ead0f8be76b
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 16:57:46 2014 -0800

    glamor: Track the next vertex offset as we go in render accel.
    
    I want to extract the VBO mapping code, and as part of that I need to
    get the global vbo_offset munging to stop.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index c93f483..b23c12b 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -702,7 +702,7 @@ void glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
                                        glamor_composite_shader *shader,
                                        struct blendinfo *op_info);
 
-void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts);
+void *glamor_setup_composite_vbo(ScreenPtr screen, int n_verts);
 
 /* glamor_trapezoid.c */
 void glamor_trapezoids(CARD8 op,
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 7e25cd5..69a22d9 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -701,7 +701,7 @@ glamor_composite_with_copy(CARD8 op,
     return ret;
 }
 
-void
+void *
 glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -765,6 +765,8 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
         glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
     }
     glamor_put_context(glamor_priv);
+
+    return glamor_priv->vb + glamor_priv->vbo_offset;
 }
 
 static void
@@ -1226,7 +1228,6 @@ glamor_composite_with_shader(CARD8 op,
     GLfloat dst_xscale, dst_yscale;
     GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1;
     struct shader_key key, key_ca;
-    float *vertices;
     int dest_x_off, dest_y_off;
     int source_x_off, source_y_off;
     int mask_x_off, mask_y_off;
@@ -1303,9 +1304,10 @@ glamor_composite_with_shader(CARD8 op,
     while (nrect) {
         int mrect, rect_processed;
         int vb_stride;
+        float *vertices;
 
         mrect = nrect > nrect_max ? nrect_max : nrect;
-        glamor_setup_composite_vbo(screen, mrect * vert_stride);
+        vertices = glamor_setup_composite_vbo(screen, mrect * vert_stride);
         rect_processed = mrect;
         vb_stride = glamor_priv->vb_stride / sizeof(float);
         while (mrect--) {
@@ -1331,7 +1333,7 @@ glamor_composite_with_shader(CARD8 op,
                 ("dest(%d,%d) source(%d %d) mask (%d %d), width %d height %d \n",
                  x_dest, y_dest, x_source, y_source, x_mask, y_mask, width,
                  height);
-            vertices = (float *) (glamor_priv->vb + glamor_priv->vbo_offset);
+
             assert(glamor_priv->vbo_offset <
                    glamor_priv->vbo_size - glamor_priv->vb_stride);
             glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale,
@@ -1361,10 +1363,14 @@ glamor_composite_with_shader(CARD8 op,
                                                      y_mask + height,
                                                      glamor_priv->yInverted,
                                                      vertices, vb_stride);
+                vertices += 2;
             }
             glamor_priv->render_nr_verts += 4;
             glamor_priv->vbo_offset += glamor_priv->vb_stride * 4;
             rects++;
+
+            /* We've incremented by one of our 4 verts, now do the other 3. */
+            vertices += 3 * vb_stride;
         }
         glamor_flush_composite_rects(screen);
         nrect -= rect_processed;
commit 438d8aceec2d4af48917a7dfecacf11cd4f4b5ce
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 13:29:08 2014 -0800

    glamor: Move glamor_emit_composite_vert() to traps, where it's used.
    
    It's only used in the nonantialiased, triangle-based trapezoids path.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index fe4b423..c93f483 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -703,10 +703,6 @@ void glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
                                        struct blendinfo *op_info);
 
 void glamor_setup_composite_vbo(ScreenPtr screen, int n_verts);
-void glamor_emit_composite_vert(ScreenPtr screen,
-                                const float *src_coords,
-                                const float *mask_coords,
-                                const float *dst_coords, int i);
 
 /* glamor_trapezoid.c */
 void glamor_trapezoids(CARD8 op,
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 98343c3..7e25cd5 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -767,31 +767,6 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
     glamor_put_context(glamor_priv);
 }
 
-void
-glamor_emit_composite_vert(ScreenPtr screen,
-                           const float *src_coords,
-                           const float *mask_coords,
-                           const float *dst_coords, int i)
-{
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    float *vb = (float *) (glamor_priv->vb + glamor_priv->vbo_offset);
-    int j = 0;
-
-    vb[j++] = dst_coords[i * 2 + 0];
-    vb[j++] = dst_coords[i * 2 + 1];
-    if (glamor_priv->has_source_coords) {
-        vb[j++] = src_coords[i * 2 + 0];
-        vb[j++] = src_coords[i * 2 + 1];
-    }
-    if (glamor_priv->has_mask_coords) {
-        vb[j++] = mask_coords[i * 2 + 0];
-        vb[j++] = mask_coords[i * 2 + 1];
-    }
-
-    glamor_priv->render_nr_verts++;
-    glamor_priv->vbo_offset += glamor_priv->vb_stride;
-}
-
 static void
 glamor_flush_composite_rects(ScreenPtr screen)
 {
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 7bc925a..7bbee4b 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -190,6 +190,31 @@ point_inside_trapezoid(int point[2], xTrapezoid *trap, xFixed cut_y)
 }
 
 static void
+glamor_emit_composite_vert(ScreenPtr screen,
+                           const float *src_coords,
+                           const float *mask_coords,
+                           const float *dst_coords, int i)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    float *vb = (float *) (glamor_priv->vb + glamor_priv->vbo_offset);
+    int j = 0;
+
+    vb[j++] = dst_coords[i * 2 + 0];
+    vb[j++] = dst_coords[i * 2 + 1];
+    if (glamor_priv->has_source_coords) {
+        vb[j++] = src_coords[i * 2 + 0];
+        vb[j++] = src_coords[i * 2 + 1];
+    }
+    if (glamor_priv->has_mask_coords) {
+        vb[j++] = mask_coords[i * 2 + 0];
+        vb[j++] = mask_coords[i * 2 + 1];
+    }
+
+    glamor_priv->render_nr_verts++;
+    glamor_priv->vbo_offset += glamor_priv->vb_stride;
+}
+
+static void
 glamor_emit_composite_triangle(ScreenPtr screen,
                                const float *src_coords,
                                const float *mask_coords,
commit bce5ec4f411134114c6ee2715f293a2250ee8800
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 24 12:14:04 2013 -0800

    glamor: Don't forget to set GL_INVALIDATE_RANGE_BIT on GL_ARB_mbr.
    
    We don't need any current contents of the buffer, and this allows an
    implementation to make a temporary BO for a streamed upload if it
    wants to.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index f8d103d..98343c3 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -731,7 +731,8 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
                                            glamor_priv->vbo_offset,
                                            vert_size,
                                            GL_MAP_WRITE_BIT |
-                                           GL_MAP_UNSYNCHRONIZED_BIT);
+                                           GL_MAP_UNSYNCHRONIZED_BIT |
+                                           GL_MAP_INVALIDATE_RANGE_BIT);
         assert(glamor_priv->vb != NULL);
         glamor_priv->vb -= glamor_priv->vbo_offset;
     }
commit 25be6b384298a7769fedb6d9b5bdc370398c9c95
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Jan 12 07:18:50 2014 +0800

    glamor: Fix a mismatched glamor_get/put_context().
    
    We don't call GL in this function any more, so we can just drop the
    get.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 9f6f1b1..6a7b528 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -46,8 +46,6 @@ static const char *
 _glamor_create_getcolor_fs_source(ScreenPtr screen, int stops_count,
                                   int use_array)
 {
-    glamor_screen_private *glamor_priv;
-
     char *gradient_fs = NULL;
 
 #define gradient_fs_getcolor\
@@ -174,9 +172,6 @@ _glamor_create_getcolor_fs_source(ScreenPtr screen, int stops_count,
         "    return gradient_color;\n"
         "}\n";
 
-    glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
-
     if (use_array) {
         XNFasprintf(&gradient_fs,
                     gradient_fs_getcolor, stops_count, stops_count);
commit bd09292debbb810db06b187d4e61c9416b5e565e
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 14:03:26 2013 -0800

    glamor: Add a note about the state of GL_ARB_map_buffer_range.
    
    GLES2 Xephyr is failing due to lack of glMapBuffer() with the read
    bits set, and I decided to see if we can just switch everything to
    glMapBufferRange().  I'm undecided, and it largely depends on whether
    we find people are interested in using glamor for the windows X server.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index fa753bb..fe9f761 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -319,6 +319,19 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 
     gl_version = glamor_gl_get_version();
 
+    /* We'd like to require GL_ARB_map_buffer_range or
+     * GL_OES_map_buffer_range, since it offers more information to
+     * the driver than plain old glMapBuffer() or glBufferSubData().
+     * It's been supported on Mesa on the desktop since 2009 and on
+     * GLES2 since October 2012.  It's supported on Apple's iOS
+     * drivers for SGX535 and A7, but apparently not on most Android
+     * devices (the OES extension spec wasn't released until June
+     * 2012).
+     *
+     * 82% of 0 A.D. players (desktop GL) submitting hardware reports
+     * have support for it, with most of the ones lacking it being on
+     * Windows with Intel 4-series (G45) graphics or older.
+     */
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) {
             ErrorF("Require OpenGL version 1.3 or later.\n");
commit ca507d215f54e878055de8da13877bc0225bece1
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 24 16:07:12 2013 -0800

    glamor: Fix a spelling mistake in GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index f1440f3..119e4d9 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -1528,7 +1528,7 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
 
     drawable = &pixmap_priv->base.pixmap->drawable;
 
-    if (!GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv))
+    if (!GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv))
         return TRUE;
 
     old_fbo = pixmap_priv->base.fbo;
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 093a215..f8d103d 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -584,7 +584,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
     else if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
              || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
         if (picture->transform
-            || (GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(pixmap_priv)))
+            || (GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(pixmap_priv)))
             repeat_type += RepeatFix;
     }
     if (repeat_type >= RepeatFix) {
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index 9374c9d..f9550b7 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -53,7 +53,7 @@
     *(_pyscale_) = 1.0 / (_pixmap_priv_)->base.fbo->height;			\
   } while(0)
 
-#define GLAMOR_PIXMAP_FBO_NOT_EAXCT_SIZE(priv)			\
+#define GLAMOR_PIXMAP_FBO_NOT_EXACT_SIZE(priv)			\
    (priv->base.fbo->width != priv->base.pixmap->drawable.width 	\
       || priv->base.fbo->height != priv->base.pixmap->drawable.height)	\
 
commit 4e86f4236b32b61796d820714dc12457dbc92e28
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 23 18:16:01 2013 -0800

    glamor: remove dead global variable.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 77197b5..f1440f3 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -697,7 +697,6 @@ glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h,
  * Upload pixmap to a specified texture.
  * This texture may not be the one attached to it.
  **/
-int in_restore = 0;
 static void
 __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
                                   GLenum format,
commit 7f15e5aed79803fa6057fbfda7dfbacacc2e019d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Mar 3 16:58:54 2014 +0100

    Require video drivers to report that they support server managed fds
    
    This makes how we handle video drivers identical to what we do for input
    drivers, and this should make live easier for old non kms drivers.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 564567e..4e80f9e 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -38,6 +38,7 @@
 #include <unistd.h>
 #include "os.h"
 #include "hotplug.h"
+#include "systemd-logind.h"
 
 #include "xf86.h"
 #include "xf86_OSproc.h"
@@ -310,7 +311,7 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp,
                             GDevPtr gdev, int flags, intptr_t match_data)
 {
     Bool foundScreen = FALSE;
-    int entity;
+    int entity, fd, major, minor;
 
     if (gdev && gdev->screen == 0 && !xf86_check_platform_slot(dev))
         return FALSE;
@@ -334,6 +335,17 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp,
         }
     }
     if (entity != -1) {
+        if ((dev->flags & XF86_PDEV_SERVER_FD) && (!drvp->driverFunc ||
+                !drvp->driverFunc(NULL, SUPPORTS_SERVER_FDS, NULL))) {
+            fd = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_FD, -1);
+            major = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_MAJOR, 0);
+            minor = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_MINOR, 0);
+            systemd_logind_release_fd(major, minor);
+            close(fd);
+            config_odev_add_int_attribute(dev->attribs, ODEV_ATTRIB_FD, -1);
+            dev->flags &= ~XF86_PDEV_SERVER_FD;
+        }
+
         if (drvp->platformProbe(drvp, entity, flags, dev, match_data))
             foundScreen = TRUE;
         else
diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h
index b164b7f..a81e886 100644
--- a/hw/xfree86/common/xf86str.h
+++ b/hw/xfree86/common/xf86str.h
@@ -256,7 +256,8 @@ typedef enum {
     RR_GET_INFO,
     RR_SET_CONFIG,
     RR_GET_MODE_MM,
-    GET_REQUIRED_HW_INTERFACES = 10
+    GET_REQUIRED_HW_INTERFACES = 10,
+    SUPPORTS_SERVER_FDS = 11,
 } xorgDriverFuncOp;
 
 typedef Bool xorgDriverFuncProc(ScrnInfoPtr, xorgDriverFuncOp, void *);
commit 76af81bdf8ade158d7cef718ff6cf31cbf641a9a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Mar 3 16:07:16 2014 +0100

    xf86platformBus: Make doPlatformProbe accept a NULL gdev argument
    
    And use it from xf86platformAddDevice too, instead of directly calling
    drvp->platformProbe.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 4447e19..564567e 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -312,13 +312,13 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp,
     Bool foundScreen = FALSE;
     int entity;
 
-    if (gdev->screen == 0 && !xf86_check_platform_slot(dev))
+    if (gdev && gdev->screen == 0 && !xf86_check_platform_slot(dev))
         return FALSE;
 
     entity = xf86ClaimPlatformSlot(dev, drvp, 0,
-                                   gdev, gdev->active);
+                                   gdev, gdev ? gdev->active : 0);
 
-    if ((entity == -1) && (gdev->screen > 0)) {
+    if ((entity == -1) && gdev && (gdev->screen > 0)) {
         unsigned nent;
 
         for (nent = 0; nent < xf86NumEntities; nent++) {
@@ -420,7 +420,6 @@ xf86platformAddDevice(int index)
 {
     int i, old_screens, scr_index;
     DriverPtr drvp = NULL;
-    int entity;
     screenLayoutPtr layout;
     static const char *hotplug_driver_name = "modesetting";
 
@@ -440,11 +439,8 @@ xf86platformAddDevice(int index)
         return -1;
 
     old_screens = xf86NumGPUScreens;
-    entity = xf86ClaimPlatformSlot(&xf86_platform_devices[index],
-                                   drvp, 0, 0, 0);
-    if (!drvp->platformProbe(drvp, entity, PLATFORM_PROBE_GPU_SCREEN, &xf86_platform_devices[index], 0)) {
-        xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL);
-    }
+    doPlatformProbe(&xf86_platform_devices[index], drvp, NULL,
+                    PLATFORM_PROBE_GPU_SCREEN, 0);
     if (old_screens == xf86NumGPUScreens)
         return -1;
     i = old_screens;
commit 749d25f6f0faed00a4cd906171ea6f96d76591e7
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 7 04:59:47 2014 -0500

    systemd-logind: Fix vt-enter not working when using a legacy video driver
    
    If there is only a single non kms video device (tested with the vesa driver),
    then we will never get a resume signal for a drm node, so also call vtenter
    when we get a resume for an input device.
    
    Notes:
    1) vtenter checks if it is ok to do the vtenter, so if there are kms video
    devices the calls for input device resumes are a nop
    2) This assumes that there will always be at least one server event fd
    supporting input device. Since all non legacy input-drivers will be patched
    to supported server fds this seems a safe assumption.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index abb8e44..a8406d8 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -347,7 +347,6 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data)
 
         if (pdev) {
             pdev->flags &= ~XF86_PDEV_PAUSED;
-            systemd_logind_vtenter();
         }
         else {
             pInfo->fd = fd;
@@ -355,6 +354,8 @@ message_filter(DBusConnection * connection, DBusMessage * message, void *data)
             if (info->vt_active)
                 xf86EnableInputDeviceForVTSwitch(pInfo);
         }
+        /* Always call vtenter(), in case there are only legacy video devs */
+        systemd_logind_vtenter();
     }
     return DBUS_HANDLER_RESULT_HANDLED;
 }
commit c6dea929a4951c3c048554a1ef54cf8143d9577a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Mar 3 17:00:57 2014 +0100

    config_odev_add*_attribute: Don't add the attribute to the list twice
    
    Don't do the xorg_list_append a 2nd time when updating existing attributes,
    while at it add a helper function for this to avoid code duplication.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 7971b87..530f21d 100644
--- a/config/config.c
+++ b/config/config.c
@@ -159,23 +159,38 @@ config_odev_find_attribute(struct OdevAttributes *attribs, int attrib_id)
     return NULL;
 }
 
+static struct OdevAttribute *
+config_odev_find_or_add_attribute(struct OdevAttributes *attribs, int attrib)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib);
+    if (oa)
+        return oa;
+
+    oa = calloc(1, sizeof(struct OdevAttribute));
+    if (!oa)
+        return oa;
+
+    oa->attrib_id = attrib;
+    xorg_list_append(&oa->member, &attribs->list);
+
+    return oa;
+}
+
 Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name)
 {
     struct OdevAttribute *oa;
 
-    oa = config_odev_find_attribute(attribs, attrib);
-    if (!oa)
-        oa = calloc(1, sizeof(struct OdevAttribute));
+    oa = config_odev_find_or_add_attribute(attribs, attrib);
     if (!oa)
         return FALSE;
 
-    oa->attrib_id = attrib;
     free(oa->attrib_name);
     oa->attrib_name = strdup(attrib_name);
     oa->attrib_type = ODEV_ATTRIB_STRING;
-    xorg_list_append(&oa->member, &attribs->list);
     return TRUE;
 }
 
@@ -185,16 +200,12 @@ config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
 {
     struct OdevAttribute *oa;
 
-    oa = config_odev_find_attribute(attribs, attrib);
-    if (!oa)
-        oa = calloc(1, sizeof(struct OdevAttribute));
+    oa = config_odev_find_or_add_attribute(attribs, attrib);
     if (!oa)
         return FALSE;
 
-    oa->attrib_id = attrib;
     oa->attrib_value = attrib_value;
     oa->attrib_type = ODEV_ATTRIB_INT;
-    xorg_list_append(&oa->member, &attribs->list);
     return TRUE;
 }
 
commit 2f2967173ba0b0a4f7ab013edeaaf11e7c181beb
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Mar 3 09:51:36 2014 +0100

    hashtabletest: Fix warning: format ‘%ld’ expects argument of type ...
    
    This fixes the following compiler warning:
    
    hashtabletest.c: In function ‘print_xid’:
    hashtabletest.c:15:5: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 2 has type ‘XID’ [-Wformat=]
         printf("%ld", *x);
         ^
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/test/hashtabletest.c b/test/hashtabletest.c
index ceadfa7..86a0c58 100644
--- a/test/hashtabletest.c
+++ b/test/hashtabletest.c
@@ -12,7 +12,7 @@ static void
 print_xid(void* ptr, void* v)
 {
     XID *x = v;
-    printf("%ld", *x);
+    printf("%ld", (long)(*x));
 }
 
 static void
commit b972851ce47b5e3b681a212a43dd71aab94e7a1b
Author: Dave Airlie <airlied at gmail.com>
Date:   Mon Mar 10 08:58:37 2014 +1000

    xserver: fix build since system-logind.h
    
    on tinderbox and irc
    
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Matthieu Herrb <matthieu at herrb.eu>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/include/systemd-logind.h b/include/systemd-logind.h
index 8b09081..06dd031 100644
--- a/include/systemd-logind.h
+++ b/include/systemd-logind.h
@@ -36,8 +36,8 @@ void systemd_logind_vtenter(void);
 #else
 #define systemd_logind_init()
 #define systemd_logind_fini()
-#define systemd_logind_take_fd(major, minor, path) -1
-#define systemd_logind_release_fd(dev)
+#define systemd_logind_take_fd(major, minor, path, paus) -1
+#define systemd_logind_release_fd(major, minor)
 #define systemd_logind_controls_session() 0
 #define systemd_logind_vtenter()
 #endif
commit 1c61d38528a573caadee2468ee59ea558c822e09
Merge: 5350ae1 bf35437
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 7 22:07:19 2014 -0800

    Merge remote-tracking branch 'jwrdecoede/for-keith'

commit 5350ae1d38f3c69a26421e0866ede0d2ccc3aea4
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Fri Mar 7 15:59:10 2014 +0000

    Fix xephyr build in --disable-glamor case
    
    It broke after commit 9fe052d90cca90fdf750d3a45b151be2ac7f0ebd
    "xephyr: Build support for rendering with glamor using a -glamor
    option."
    
    See http://tinderbox.x.org/builds/2014-03-07-0004/logs/xserver/#build
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 19c2ed2..859beca 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -309,9 +309,11 @@ hostx_init(void)
         | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
 
     EPHYR_DBG("mark");
+#ifdef GLAMOR
     if (ephyr_glamor)
         HostX.conn = ephyr_glamor_connect();
     else
+#endif
         HostX.conn = xcb_connect(NULL, &HostX.screen);
     if (xcb_connection_has_error(HostX.conn)) {
         fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
@@ -322,11 +324,12 @@ hostx_init(void)
     HostX.winroot = xscreen->root;
     HostX.gc = xcb_generate_id(HostX.conn);
     HostX.depth = xscreen->root_depth;
-    if (ephyr_glamor) {
+#ifdef GLAMOR
+    if (ephyr_glamor)
         HostX.visual = ephyr_glamor_get_visual();
-    } else {
+    else
+#endif
         HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
-    }
 
     xcb_create_gc(HostX.conn, HostX.gc, HostX.winroot, 0, NULL);
     cookie_WINDOW_STATE = xcb_intern_atom(HostX.conn, FALSE,
@@ -760,6 +763,7 @@ hostx_paint_rect(KdScreenInfo *screen,
 
     EPHYR_DBG("painting in screen %d\n", scrpriv->mynum);
 
+#ifdef GLAMOR
     if (ephyr_glamor) {
         BoxRec box;
         RegionRec region;
@@ -774,6 +778,7 @@ hostx_paint_rect(KdScreenInfo *screen,
         RegionUninit(&region);
         return;
     }
+#endif
 
     /*
      *  Copy the image data updated by the shadow layer
commit 78e508c9379b3976ac8e76b7aaa90ba86ad4e443
Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Mon Dec 30 09:15:41 2013 -0600

    dix: Clear any existing selections before initializing privates
    
    If there is a selection left over from a previous execution of the
    main loop, and that selection has privates allocated for it, the X
    server will crash. This is because dixResetPrivates() resets the
    privates refcounts to zero without accounting for the reference held
    by the selection object. When the selection is then deleted in
    InitSelections() after the call to dixResetPrivates(), the refcount
    for its privates type goes negative and bad things happen.
    
    To fix this, we should delete any existing selections before calling
    dixResetPrivates(). This will properly release the selection's
    privates and avoid the crash.
    
    A more thorough description of the problem and a test case to
    reproduce the crash is available at a previous mail:
      "Negative Selection devPrivates refcount?"
      By Andrew Eikum to xorg-devel on 10 Dec 2013
      http://lists.freedesktop.org/archives/xorg-devel/2013-December/039492.html
    
    Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/main.c b/dix/main.c
index fcc1ad3..7427e08 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -175,6 +175,9 @@ dix_main(int argc, char *argv[], char *envp[])
         clients[0] = serverClient;
         currentMaxClients = 1;
 
+        /* clear any existing selections */
+        InitSelections();
+
         /* Initialize privates before first allocation */
         dixResetPrivates();
 
@@ -192,7 +195,6 @@ dix_main(int argc, char *argv[], char *envp[])
 
         InitAtoms();
         InitEvents();
-        InitSelections();
         InitGlyphCaching();
         dixResetRegistry();
         ResetFontPrivateIndex();
commit da08316605b26830b4d8f8fb2d9e69471cdc80ab
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 31 00:07:42 2013 -0800

    glamor: Add support for DRI3.
    
    The render-nodes case is untested.
    
    v2: Add a flag for wayland to suppress the native DRI3 support.
        Wayland isn't running as a master itself, so it can't do the auth
        on its own and has to ask the compositor to do it for us.  Dropped
        XXX about randr provider -- the conclusion from discussion with
        keithp was that if the driver's dri3_open for a provider on a
        different screen, that's a core dri3 bug.
    v3: Don't put quite so much under GLAMOR_NO_DRI3, and add a comment
        explaining what this is about.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 041004e..e12f497 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -67,10 +67,12 @@ typedef enum glamor_pixmap_type {
 #define GLAMOR_USE_SCREEN		(1 << 1)
 #define GLAMOR_USE_PICTURE_SCREEN 	(1 << 2)
 #define GLAMOR_USE_EGL_SCREEN		(1 << 3)
+#define GLAMOR_NO_DRI3			(1 << 4)
 #define GLAMOR_VALID_FLAGS      (GLAMOR_INVERTED_Y_AXIS  		\
 				 | GLAMOR_USE_SCREEN 			\
                                  | GLAMOR_USE_PICTURE_SCREEN		\
-				 | GLAMOR_USE_EGL_SCREEN)
+				 | GLAMOR_USE_EGL_SCREEN                \
+                                 | GLAMOR_NO_DRI3)
 
 /* @glamor_init: Initialize glamor internal data structure.
  *
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 56d8913..05e6bd0 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -50,6 +50,7 @@
 
 #include "glamor.h"
 #include "glamor_priv.h"
+#include "dri3.h"
 
 static const char glamor_name[] = "glamor";
 
@@ -68,6 +69,7 @@ struct glamor_egl_screen_private {
     EGLDisplay display;
     EGLContext context;
     EGLint major, minor;
+    char *device_path;
 
     CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr CloseScreen;
@@ -627,10 +629,67 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl,
     return FALSE;
 }
 
+static int
+glamor_dri3_open(ScreenPtr screen,
+                 RRProviderPtr provider,
+                 int *fdp)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_egl_screen_private *glamor_egl =
+        glamor_egl_get_screen_private(scrn);
+    int fd;
+    drm_magic_t magic;
+
+    fd = open(glamor_egl->device_path, O_RDWR|O_CLOEXEC);
+    if (fd < 0)
+        return BadAlloc;
+
+    /* Before FD passing in the X protocol with DRI3 (and increased
+     * security of rendering with per-process address spaces on the
+     * GPU), the kernel had to come up with a way to have the server
+     * decide which clients got to access the GPU, which was done by
+     * each client getting a unique (magic) number from the kernel,
+     * passing it to the server, and the server then telling the
+     * kernel which clients were authenticated for using the device.
+     *
+     * Now that we have FD passing, the server can just set up the
+     * authentication on its own and hand the prepared FD off to the
+     * client.
+     */
+    if (drmGetMagic(fd, &magic) < 0) {
+        if (errno == EACCES) {
+            /* Assume that we're on a render node, and the fd is
+             * already as authenticated as it should be.
+             */
+            *fdp = fd;
+            return Success;
+        } else {
+            close(fd);
+            return BadMatch;
+        }
+    }
+
+    if (drmAuthMagic(glamor_egl->fd, magic) < 0) {
+        close(fd);
+        return BadMatch;
+    }
+
+    *fdp = fd;
+    return Success;
+}
+
+static dri3_screen_info_rec glamor_dri3_info = {
+    .version = 0,
+    .open = glamor_dri3_open,
+    .pixmap_from_fd = glamor_pixmap_from_fd,
+    .fd_from_pixmap = glamor_fd_from_pixmap,
+};
+
 void
 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
 
@@ -642,6 +701,30 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 
     glamor_ctx->get_context = glamor_egl_get_context;
     glamor_ctx->put_context = glamor_egl_put_context;
+
+    if (glamor_egl->dri3_capable) {
+        /* Tell the core that we have the interfaces for import/export
+         * of pixmaps.
+         */
+        glamor_enable_dri3(screen);
+
+        /* If the driver wants to do its own auth dance (e.g. Xwayland
+         * on pre-3.15 kernels that don't have render nodes and thus
+         * has the wayland compositor as a master), then it needs us
+         * to stay out of the way and let it init DRI3 on its own.
+         */
+        if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) {
+            /* To do DRI3 device FD generation, we need to open a new fd
+             * to the same device we were handed in originally.
+             */
+            glamor_egl->device_path = drmGetDeviceNameFromFd(glamor_egl->fd);
+
+            if (!dri3_screen_init(screen, &glamor_dri3_info)) {
+                xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                           "Failed to initialize DRI3.\n");
+            }
+        }
+    }
 }
 
 static void
@@ -658,6 +741,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn)
         if (glamor_egl->gbm)
             gbm_device_destroy(glamor_egl->gbm);
 #endif
+        free(glamor_egl->device_path);
+
         scrn->FreeScreen = glamor_egl->saved_free_screen;
         free(glamor_egl);
         scrn->FreeScreen(scrn);
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
index bb1b511..85e1c0c 100644
--- a/hw/xfree86/glamor_egl/Makefile.am
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -36,5 +36,8 @@ libglamoregl_la_LIBADD = \
 	$(top_builddir)/glamor/libglamor.la \
 	$()
 
-AM_CPPFLAGS = $(XORG_INCS)
+AM_CPPFLAGS = $(XORG_INCS) \
+	-I$(top_srcdir)/dri3 \
+	$()
+
 AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
commit fb4a1e6ef6f80a7670e92cab2bc490d4afd80a9b
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 18:49:46 2013 -0800

    glamor: Rename the DRI-related pixmap functions.
    
    There was confusion over whether they should have egl in the name, and
    they had DRI3 in the name even though they're useful to have without
    DRI3.
    
    v2: Just rename glamor_name_from_pixmap for now -- I'd accidentally
        conflict-resolved in adding new parameters from a later commit.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 85fd560..fa753bb 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -567,16 +567,16 @@ glamor_enable_dri3(ScreenPtr screen)
 }
 
 Bool
-glamor_is_dri3_support_enabled(ScreenPtr screen)
+glamor_supports_pixmap_import_export(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     return glamor_priv->dri3_enabled;
 }
 
-int
-glamor_dri3_fd_from_pixmap(ScreenPtr screen,
-                           PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+_X_EXPORT int
+glamor_fd_from_pixmap(ScreenPtr screen,
+                      PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
 {
     glamor_pixmap_private *pixmap_priv;
     glamor_screen_private *glamor_priv =
@@ -600,7 +600,7 @@ glamor_dri3_fd_from_pixmap(ScreenPtr screen,
 }
 
 int
-glamor_dri3_name_from_pixmap(PixmapPtr pixmap)
+glamor_name_from_pixmap(PixmapPtr pixmap)
 {
     glamor_pixmap_private *pixmap_priv;
     glamor_screen_private *glamor_priv =
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 89e7d80..041004e 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -173,21 +173,23 @@ extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr,
                                                       unsigned int, Bool,
                                                       CARD16 *, CARD32 *);
 
-/* @glamor_is_dri3_support_enabled: Returns if DRI3 support is enabled.
+/* @glamor_supports_pixmap_import_export: Returns whether
+ * glamor_fd_from_pixmap(), glamor_name_from_pixmap(), and
+ * glamor_pixmap_from_fd() are supported.
  *
  * @screen: Current screen pointer.
  *
- * To have DRI3 support enabled, glamor and glamor_egl need to be initialized,
- * and glamor_egl_init_textured_pixmap need to be called. glamor also
- * has to be compiled with gbm support.
- * The EGL layer need to have the following extensions working:
+ * To have DRI3 support enabled, glamor and glamor_egl need to be
+ * initialized. glamor also has to be compiled with gbm support.
+ *
+ * The EGL layer needs to have the following extensions working:
+ *
  * .EGL_KHR_gl_texture_2D_image
  * .EGL_EXT_image_dma_buf_import
- * If DRI3 support is not enabled, the following helpers will return an error.
  * */
-extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
+extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen);
 
-/* @glamor_dri3_fd_from_pixmap: DRI3 helper to get a dma-buf fd from a pixmap.
+/* @glamor_fd_from_pixmap: Get a dma-buf fd from a pixmap.
  *
  * @screen: Current screen pointer.
  * @pixmap: The pixmap from which we want the fd.
@@ -198,22 +200,25 @@ extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
  * content.
  * Returns the fd on success, -1 on error.
  * */
-extern _X_EXPORT int glamor_dri3_fd_from_pixmap(ScreenPtr screen,
-                                                PixmapPtr pixmap,
-                                                CARD16 *stride, CARD32 *size);
+extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen,
+                                           PixmapPtr pixmap,
+                                           CARD16 *stride, CARD32 *size);
 
-/* @glamor_dri3_name_from_pixmap: helper to get an gem name from a pixmap.
+/**
+ * @glamor_name_from_pixmap: Gets a gem name from a pixmap.
  *
  * @pixmap: The pixmap from which we want the gem name.
  *
- * the pixmap and the buffer associated by the gem name will share the same
- * content. This function can be used by the DDX to support DRI2, but needs
- * glamor DRI3 support to be activated.
+ * the pixmap and the buffer associated by the gem name will share the
+ * same content. This function can be used by the DDX to support DRI2,
+ * and needs the same set of buffer export GL extensions as DRI3
+ * support.
+ *
  * Returns the name on success, -1 on error.
  * */
-extern _X_EXPORT int glamor_dri3_name_from_pixmap(PixmapPtr pixmap);
+extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap);
 
-/* @glamor_egl_dri3_pixmap_from_fd: DRI3 helper to get a pixmap from a dma-buf fd.
+/* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd.
  *
  * @screen: Current screen pointer.
  * @fd: The dma-buf fd to import.
@@ -225,13 +230,13 @@ extern _X_EXPORT int glamor_dri3_name_from_pixmap(PixmapPtr pixmap);
  *
  * Returns a valid pixmap if the import succeeded, else NULL.
  * */
-extern _X_EXPORT PixmapPtr glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
-                                                          int fd,
-                                                          CARD16 width,
-                                                          CARD16 height,
-                                                          CARD16 stride,
-                                                          CARD8 depth,
-                                                          CARD8 bpp);
+extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen,
+                                                 int fd,
+                                                 CARD16 width,
+                                                 CARD16 height,
+                                                 CARD16 stride,
+                                                 CARD8 depth,
+                                                 CARD8 bpp);
 
 #ifdef GLAMOR_FOR_XORG
 
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 9dcba71..56d8913 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -453,12 +453,12 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 #endif
 }
 
-PixmapPtr
-glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
-                               int fd,
-                               CARD16 width,
-                               CARD16 height,
-                               CARD16 stride, CARD8 depth, CARD8 bpp)
+_X_EXPORT PixmapPtr
+glamor_pixmap_from_fd(ScreenPtr screen,
+                      int fd,
+                      CARD16 width,
+                      CARD16 height,
+                      CARD16 stride, CARD8 depth, CARD8 bpp)
 {
 #ifdef GLAMOR_HAS_GBM
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
commit 2d20f75b60276508424997d9fa8c5b97d8f1d92b
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 22:19:07 2013 -0800

    xorg: Connect up the glamor XV code, xorg DDX-only for now.
    
    Porting this code to be non-xorg-dependent is going to take
    significant hacking, so just dump it in the glamoregl module for the
    moment, so I can hack on it while regression testing.
    
    v2: Fix compiler warnings by adding #include dix-config.h at the top,
        don't try to auto-init (I'll try to fix the xv ABI later).
    v3: Fix last minute breakage of having reintroduced xf86ScrnToScreen
        (one of the compat macros).  Just use the drawable's pScreen instead.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 12a57c4..77492bc 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -37,7 +37,6 @@ libglamor_la_SOURCES = \
 	glamor_window.c\
 	glamor_fbo.c\
 	glamor_compositerects.c\
-	glamor_xv.c\
 	glamor_utils.h\
 	glamor.h
 
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 08ffd26..89e7d80 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -35,6 +35,9 @@
 #include <picturestr.h>
 #include <fb.h>
 #include <fbpict.h>
+#ifdef GLAMOR_FOR_XORG
+#include <xf86xv.h>
+#endif
 
 struct glamor_context;
 
@@ -434,7 +437,7 @@ extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC,
 extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
                                            int mode, int n, DDXPointPtr points);
 
-#if 0
+#ifdef GLAMOR_FOR_XORG
 extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen,
                                                     int num_texture_ports);
 #endif
diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c
index fb5b855..d7e1836 100644
--- a/glamor/glamor_eglmodule.c
+++ b/glamor/glamor_eglmodule.c
@@ -41,7 +41,7 @@ static XF86ModuleVersionInfo VersRec = {
     MODINFOSTRING1,
     MODINFOSTRING2,
     XORG_VERSION_CURRENT,
-    0, 5, 1, /* version */
+    1, 0, 0, /* version */
     ABI_CLASS_ANSIC,            /* Only need the ansic layer */
     ABI_ANSIC_VERSION,
     MOD_CLASS_NONE,
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index dc39476..fb90457 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -32,10 +32,14 @@
  * Xv acceleration implementation
  */
 
-#include "glamor_priv.h"
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
 
-#ifdef GLAMOR_XV
 #include "xf86xv.h"
+#define GLAMOR_FOR_XORG
+#include "glamor_priv.h"
+
 #include <X11/extensions/Xv.h>
 #include "fourcc.h"
 /* Reference color space transform data */
@@ -430,7 +434,7 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
                     Bool sync,
                     RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
 {
-    ScreenPtr screen = xf86ScrnToScreen(pScrn);
+    ScreenPtr screen = pDrawable->pScreen;
     glamor_port_private *port_priv = (glamor_port_private *) data;
     INT32 x1, x2, y1, y2;
     int srcPitch, srcPitch2;
@@ -614,12 +618,3 @@ glamor_xv_init(ScreenPtr screen, int num_texture_ports)
     }
     return adapt;
 }
-#else
-#if 0
-XF86VideoAdaptorPtr
-glamor_xv_init(ScreenPtr screen, int num_texture_ports)
-{
-    return NULL;
-}
-#endif
-#endif
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
index 827e033..bb1b511 100644
--- a/hw/xfree86/glamor_egl/Makefile.am
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -24,6 +24,7 @@ module_LTLIBRARIES = libglamoregl.la
 libglamoregl_la_SOURCES = \
 	$(top_srcdir)/glamor/glamor_egl.c \
 	$(top_srcdir)/glamor/glamor_eglmodule.c \
+	$(top_srcdir)/glamor/glamor_xv.c \
 	$()
 
 libglamoregl_la_LDFLAGS = \
commit 8d1cca30638f8a12c09efee27e9dedd90322b40e
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 16:44:15 2013 -0800

    xorg: Build a glamor_egl module.
    
    This is not exposing the API we want long term, but it should get
    existing DDX drivers up and running while we massage the API into
    shape.
    
    v2: Use LIBADD instead of LDFLAGS to fix deps on libglamor.la, and use
        version 0.5.1 (the point it was forked from the external repo).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/configure.ac b/configure.ac
index 5934950..74819bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -806,6 +806,8 @@ LIBAPPLEWM="applewm >= 1.4"
 LIBDMX="dmx >= 1.0.99.1"
 LIBDRI="dri >= 7.8.0"
 LIBDRM="libdrm >= 2.3.0"
+LIBEGL="egl"
+LIBGBM="gbm >= 9"
 LIBGL="gl >= 7.1.0"
 LIBXEXT="xext >= 1.0.99.4"
 LIBXFONT="xfont >= 1.4.2"
@@ -2070,7 +2072,15 @@ AM_CONDITIONAL([GLAMOR], [test "x$GLAMOR" = xyes])
 if test "x$GLAMOR" = xyes; then
 	AC_DEFINE(GLAMOR, 1, [Build glamor])
 	PKG_CHECK_MODULES([GLAMOR], [epoxy])
+
+	PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
+	if test "x$GBM" = xyes; then
+		AC_DEFINE(GLAMOR_HAS_GBM, 1,
+			  [Build glamor with GBM-based EGL support])
+	fi
+
 fi
+AM_CONDITIONAL([GLAMOR_EGL], [test "x$GBM" = xyes])
 
 dnl XWin DDX
 
@@ -2479,6 +2489,7 @@ hw/xfree86/exa/Makefile
 hw/xfree86/exa/man/Makefile
 hw/xfree86/fbdevhw/Makefile
 hw/xfree86/fbdevhw/man/Makefile
+hw/xfree86/glamor_egl/Makefile
 hw/xfree86/i2c/Makefile
 hw/xfree86/int10/Makefile
 hw/xfree86/loader/Makefile
diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c
index 5ddd602..fb5b855 100644
--- a/glamor/glamor_eglmodule.c
+++ b/glamor/glamor_eglmodule.c
@@ -30,6 +30,7 @@
 #include "dix-config.h"
 
 #include <xorg-server.h>
+#include <xf86.h>
 #define GLAMOR_FOR_XORG
 #include <xf86Module.h>
 #include "glamor.h"
@@ -40,7 +41,7 @@ static XF86ModuleVersionInfo VersRec = {
     MODINFOSTRING1,
     MODINFOSTRING2,
     XORG_VERSION_CURRENT,
-    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+    0, 5, 1, /* version */
     ABI_CLASS_ANSIC,            /* Only need the ansic layer */
     ABI_ANSIC_VERSION,
     MOD_CLASS_NONE,
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 9672904..73e1b4c 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -14,6 +14,10 @@ DRI3_BUILDDIR = $(top_builddir)/dri3
 DRI3_LIB = $(DRI3_BUILDDIR)/libdri3.la
 endif
 
+if GLAMOR_EGL
+GLAMOR_EGL_SUBDIR = glamor_egl
+endif
+
 if XF86UTILS
 XF86UTILS_SUBDIR = utils
 endif
@@ -33,7 +37,8 @@ endif
 SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
 	  ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \
 	  $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
-	  fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man
+	  fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \
+	  $(GLAMOR_EGL_SUBDIR)
 
 DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
                parser ramdac shadowfb vbe vgahw \
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
new file mode 100644
index 0000000..827e033
--- /dev/null
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -0,0 +1,39 @@
+# Copyright © 2013 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.
+
+module_LTLIBRARIES = libglamoregl.la
+
+libglamoregl_la_SOURCES = \
+	$(top_srcdir)/glamor/glamor_egl.c \
+	$(top_srcdir)/glamor/glamor_eglmodule.c \
+	$()
+
+libglamoregl_la_LDFLAGS = \
+	-avoid-version \
+	$(GBM_LIBS) \
+	$()
+
+libglamoregl_la_LIBADD = \
+	$(top_builddir)/glamor/libglamor.la \
+	$()
+
+AM_CPPFLAGS = $(XORG_INCS)
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 7c77956..754e81e 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -481,4 +481,7 @@
 /* Build GLAMOR */
 #undef GLAMOR
 
+/* Build glamor's GBM-based EGL support */
+#undef GLAMOR_HAS_GBM
+
 #endif /* _DIX_CONFIG_H_ */
commit fa2e78788327c41bfd45b3de3c71bf9c26dcc85e
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 20 10:41:43 2013 -0800

    xephyr: Pass incoming XCB events to the Xlib event filter.
    
    This is the same thing that Qt ended up doing to get DRI2's event
    mangling to happen despite using an XCB event loop.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 75a6fcb..def50d8 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -1223,6 +1223,9 @@ ephyrPoll(void)
             break;
         }
 
+        if (ephyr_glamor)
+            ephyr_glamor_process_event(xev);
+
         free(xev);
     }
 }
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index a937c1a..d56907f 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -29,12 +29,17 @@
 
 #include <stdlib.h>
 #include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#undef Xcalloc
+#undef Xrealloc
+#undef Xfree
 #include <X11/Xlib-xcb.h>
 #include <xcb/xcb_aux.h>
 #include <pixman.h>
 #include <epoxy/glx.h>
 #include "ephyr_glamor_glx.h"
 #include "os.h"
+#include <X11/Xproto.h>
 
 /** @{
  *
@@ -218,6 +223,40 @@ ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
     glXSwapBuffers(dpy, glamor->glx_win);
 }
 
+/**
+ * Xlib-based handling of xcb events for glamor.
+ *
+ * We need to let the Xlib event filtering run on the event so that
+ * Mesa's dri2_glx.c userspace event mangling gets run, and we
+ * correctly get our invalidate events propagated into the driver.
+ */
+void
+ephyr_glamor_process_event(xcb_generic_event_t *xev)
+{
+
+    uint32_t response_type = xev->response_type & 0x7f;
+    /* Note the types on wire_to_event: there's an Xlib XEvent (with
+     * the broken types) that it returns, and a protocol xEvent that
+     * it inspects.
+     */
+    Bool (*wire_to_event)(Display *dpy, XEvent *ret, xEvent *event);
+
+    XLockDisplay(dpy);
+    /* Set the event handler to NULL to get access to the current one. */
+    wire_to_event = XESetWireToEvent(dpy, response_type, NULL);
+    if (wire_to_event) {
+        XEvent processed_event;
+
+        /* OK they had an event handler.  Plug it back in, and call
+         * through to it.
+         */
+        XESetWireToEvent(dpy, response_type, wire_to_event);
+        xev->sequence = LastKnownRequestProcessed(dpy);
+        wire_to_event(dpy, &processed_event, (xEvent *)xev);
+    }
+    XUnlockDisplay(dpy);
+}
+
 struct ephyr_glamor *
 ephyr_glamor_glx_screen_init(xcb_window_t win)
 {
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.h b/hw/kdrive/ephyr/ephyr_glamor_glx.h
index 950beff..8995e1e 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.h
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.h
@@ -53,10 +53,21 @@ ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor);
 void
 ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
                               struct pixman_region16 *damage);
-#else
+
+void
+ephyr_glamor_process_event(xcb_generic_event_t *xev);
+
+#else /* !GLAMOR */
+
 static inline void
 ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
                               struct pixman_region16 *damage)
 {
 }
-#endif
+
+static inline void
+ephyr_glamor_process_event(xcb_generic_event_t *xev)
+{
+}
+
+#endif /* !GLAMOR */
commit 9fe052d90cca90fdf750d3a45b151be2ac7f0ebd
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 18 13:24:14 2013 -0800

    xephyr: Build support for rendering with glamor using a -glamor option.
    
    v2: Avoid making the Ximage for the screen that we'll never use, and
        drive the screen pixmap creation for glamor ourselves.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com> (v1)
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/configure.ac b/configure.ac
index 0fb2fc3..5934950 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2319,6 +2319,9 @@ if test "$KDRIVE" = yes; then
     if test "x$DRI" = xyes && test "x$GLX" = xyes; then
         XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS libdrm xcb-glx xcb-xf86dri > 1.6"
     fi
+    if test "x$GLAMOR" = xyes; then
+        XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS x11-xcb"
+    fi
 
     if test "x$XEPHYR" = xauto; then
         PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [XEPHYR="yes"], [XEPHYR="no"])
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 7d8228c..85fd560 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -123,6 +123,17 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap)
     glamor_priv->back_pixmap = back_pixmap;
 }
 
+uint32_t
+glamor_get_pixmap_texture(PixmapPtr pixmap)
+{
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY)
+        return 0;
+
+    return pixmap_priv->base.fbo->tex;
+}
+
 PixmapPtr
 glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
                      unsigned int usage)
diff --git a/glamor/glamor.h b/glamor/glamor.h
index eec6872..08ffd26 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -124,6 +124,8 @@ extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen);
 extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap,
                                                PixmapPtr *back_pixmap);
 
+extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap);
+
 /* @glamor_glyphs_init: Initialize glyphs internal data structures.
  *
  * @pScreen: Current screen pointer.
diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am
index 6b790fd..040993c 100644
--- a/hw/kdrive/ephyr/Makefile.am
+++ b/hw/kdrive/ephyr/Makefile.am
@@ -27,12 +27,20 @@ AM_CPPFLAGS = 			\
 	@XEPHYR_INCS@		\
 	@XEPHYR_CFLAGS@		\
 	-I$(top_srcdir)		\
+	-I$(top_srcdir)/glamor	\
 	-I$(top_srcdir)/exa
 
 if XV
 XV_SRCS = ephyrvideo.c
 endif
 
+if GLAMOR
+GLAMOR_SRCS = \
+	ephyr_glamor_glx.c \
+	ephyr_glamor_glx.h \
+	()
+endif
+
 if DRI
 DRI_SRCS =			\
 	ephyrdriext.c		\
@@ -59,14 +67,24 @@ Xephyr_SOURCES = \
 	hostx.h \
 	$(XV_SRCS) \
 	$(DRI_SRCS) \
+	$(GLAMOR_SRCS) \
 	$()
 
+if GLAMOR
+AM_CPPFLAGS += $(XLIB_CFLAGS)
+XEPHYR_GLAMOR_LIB = \
+	$(top_builddir)/glamor/libglamor.la \
+	$(top_builddir)/glamor/libglamor_egl_stubs.la \
+	$()
+endif
+
 Xephyr_LDADD = 						\
 	$(top_builddir)/exa/libexa.la			\
+	$(XEPHYR_GLAMOR_LIB)				\
 	@KDRIVE_LIBS@					\
 	@XEPHYR_LIBS@
 
-Xephyr_DEPENDENCIES = @KDRIVE_LOCAL_LIBS@
+Xephyr_DEPENDENCIES = @KDRIVE_LOCAL_LIBS@ $(XEPHYR_GLAMOR_LIB)
 
 Xephyr_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 9681273..75a6fcb 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -43,9 +43,15 @@
 #include "ephyrglxext.h"
 #endif                          /* XF86DRI */
 
+#ifdef GLAMOR
+#include "glamor.h"
+#endif
+#include "ephyr_glamor_glx.h"
+
 #include "xkbsrv.h"
 
 extern int KdTsPhyScreen;
+extern Bool ephyr_glamor;
 
 KdKeyboardInfo *ephyrKbd;
 KdPointerInfo *ephyrMouse;
@@ -326,15 +332,19 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen)
         int nbox;
         BoxPtr pbox;
 
-        nbox = RegionNumRects(pRegion);
-        pbox = RegionRects(pRegion);
-
-        while (nbox--) {
-            hostx_paint_rect(screen,
-                             pbox->x1, pbox->y1,
-                             pbox->x1, pbox->y1,
-                             pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
-            pbox++;
+        if (ephyr_glamor) {
+            ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
+        } else {
+            nbox = RegionNumRects(pRegion);
+            pbox = RegionRects(pRegion);
+
+            while (nbox--) {
+                hostx_paint_rect(screen,
+                                 pbox->x1, pbox->y1,
+                                 pbox->x1, pbox->y1,
+                                 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+                pbox++;
+            }
         }
         DamageEmpty(scrpriv->pDamage);
     }
@@ -662,6 +672,7 @@ ephyrInitScreen(ScreenPtr pScreen)
     return TRUE;
 }
 
+
 Bool
 ephyrFinishInitScreen(ScreenPtr pScreen)
 {
@@ -679,6 +690,12 @@ ephyrFinishInitScreen(ScreenPtr pScreen)
     return TRUE;
 }
 
+/**
+ * Called by kdrive after calling down the
+ * pScreen->CreateScreenResources() chain, this gives us a chance to
+ * make any pixmaps after the screen and all extensions have been
+ * initialized.
+ */
 Bool
 ephyrCreateResources(ScreenPtr pScreen)
 {
@@ -693,8 +710,13 @@ ephyrCreateResources(ScreenPtr pScreen)
         return KdShadowSet(pScreen,
                            scrpriv->randr,
                            ephyrShadowUpdate, ephyrWindowLinear);
-    else
+    else {
+#ifdef GLAMOR
+        if (ephyr_glamor)
+            ephyr_glamor_create_screen_resources(pScreen);
+#endif
         return ephyrSetInternalDamage(pScreen);
+    }
 }
 
 void
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 73fdb59..34ce460 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -80,6 +80,12 @@ typedef struct _ephyrScrPriv {
 
     KdScreenInfo *screen;
     int mynum;                  /* Screen number */
+
+    /**
+     * Per-screen Xlib-using state for glamor (private to
+     * ephyr_glamor_glx.c)
+     */
+    struct ephyr_glamor *glamor;
 } EphyrScrPriv;
 
 extern KdCardFuncs ephyrFuncs;
@@ -203,6 +209,14 @@ void
 void
  ephyrDrawFini(ScreenPtr pScreen);
 
+/* hostx.c glamor support */
+Bool ephyr_glamor_init(ScreenPtr pScreen);
+Bool ephyr_glamor_create_screen_resources(ScreenPtr pScreen);
+void ephyr_glamor_enable(ScreenPtr pScreen);
+void ephyr_glamor_disable(ScreenPtr pScreen);
+void ephyr_glamor_fini(ScreenPtr pScreen);
+void ephyr_glamor_host_paint_rect(ScreenPtr pScreen);
+
 /*ephyvideo.c*/
 
 Bool ephyrInitVideo(ScreenPtr pScreen);
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
new file mode 100644
index 0000000..a937c1a
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2013 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.
+ */
+
+/** @file ephyr_glamor_glx.c
+ *
+ * Separate file for hiding Xlib and GLX-using parts of xephyr from
+ * the rest of the server-struct-aware build.
+ */
+
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb_aux.h>
+#include <pixman.h>
+#include <epoxy/glx.h>
+#include "ephyr_glamor_glx.h"
+#include "os.h"
+
+/** @{
+ *
+ * global state for Xephyr with glamor.
+ *
+ * Xephyr can render with multiple windows, but all the windows have
+ * to be on the same X connection and all have to have the same
+ * visual.
+ */
+static Display *dpy;
+static XVisualInfo *visual_info;
+static GLXFBConfig fb_config;
+/** @} */
+
+/**
+ * Per-screen state for Xephyr with glamor.
+ */
+struct ephyr_glamor {
+    GLXContext ctx;
+    Window win;
+    GLXWindow glx_win;
+
+    GLuint tex;
+
+    GLuint texture_shader;
+    GLuint texture_shader_position_loc;
+    GLuint texture_shader_texcoord_loc;
+};
+
+static GLint
+ephyr_glamor_compile_glsl_prog(GLenum type, const char *source)
+{
+    GLint ok;
+    GLint prog;
+
+    prog = glCreateShader(type);
+    glShaderSource(prog, 1, (const GLchar **) &source, NULL);
+    glCompileShader(prog);
+    glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
+    if (!ok) {
+        GLchar *info;
+        GLint size;
+
+        glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
+        info = malloc(size);
+        if (info) {
+            glGetShaderInfoLog(prog, size, NULL, info);
+            ErrorF("Failed to compile %s: %s\n",
+                   type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
+            ErrorF("Program source:\n%s", source);
+            free(info);
+        }
+        else
+            ErrorF("Failed to get shader compilation info.\n");
+        FatalError("GLSL compile failure\n");
+    }
+
+    return prog;
+}
+
+static GLuint
+ephyr_glamor_build_glsl_prog(GLuint vs, GLuint fs)
+{
+    GLint ok;
+    GLuint prog;
+
+    prog = glCreateProgram();
+    glAttachShader(prog, vs);
+    glAttachShader(prog, fs);
+
+    glLinkProgram(prog);
+    glGetProgramiv(prog, GL_LINK_STATUS, &ok);
+    if (!ok) {
+        GLchar *info;
+        GLint size;
+
+        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
+        info = malloc(size);
+
+        glGetProgramInfoLog(prog, size, NULL, info);
+        ErrorF("Failed to link: %s\n", info);
+        FatalError("GLSL link failure\n");
+    }
+
+    return prog;
+}
+
+static void
+ephyr_glamor_setup_texturing_shader(struct ephyr_glamor *glamor)
+{
+    const char *vs_source =
+        "attribute vec2 texcoord;\n"
+        "attribute vec2 position;\n"
+        "varying vec2 t;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    t = texcoord;\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}\n";
+
+    const char *fs_source =
+        "varying vec2 t;\n"
+        "uniform sampler2D s; /* initially 0 */\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = texture2D(s, t);\n"
+        "}\n";
+
+    GLuint fs, vs, prog;
+
+    vs = ephyr_glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source);
+    fs = ephyr_glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source);
+    prog = ephyr_glamor_build_glsl_prog(vs, fs);
+
+    glamor->texture_shader = prog;
+    glamor->texture_shader_position_loc = glGetAttribLocation(prog, "position");
+    assert(glamor->texture_shader_position_loc != -1);
+    glamor->texture_shader_texcoord_loc = glGetAttribLocation(prog, "texcoord");
+    assert(glamor->texture_shader_texcoord_loc != -1);
+}
+
+xcb_connection_t *
+ephyr_glamor_connect(void)
+{
+    dpy = XOpenDisplay(NULL);
+    if (!dpy)
+        return NULL;
+
+    XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+
+    return XGetXCBConnection(dpy);
+}
+
+void
+ephyr_glamor_set_texture(struct ephyr_glamor *glamor, uint32_t tex)
+{
+    glamor->tex = tex;
+}
+
+void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+                              struct pixman_region16 *damage)
+{
+    /* Redraw the whole screen, since glXSwapBuffers leaves the back
+     * buffer undefined.
+     */
+    static const float position[] = {
+        -1, -1,
+         1, -1,
+         1,  1,
+        -1,  1,
+    };
+    static const float texcoords[] = {
+        0, 1,
+        1, 1,
+        1, 0,
+        0, 0,
+    };
+
+    glXMakeCurrent(dpy, glamor->glx_win, glamor->ctx);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glUseProgram(glamor->texture_shader);
+
+    glVertexAttribPointer(glamor->texture_shader_position_loc,
+                          2, GL_FLOAT, FALSE, 0, position);
+    glVertexAttribPointer(glamor->texture_shader_texcoord_loc,
+                          2, GL_FLOAT, FALSE, 0, texcoords);
+    glEnableVertexAttribArray(glamor->texture_shader_position_loc);
+    glEnableVertexAttribArray(glamor->texture_shader_texcoord_loc);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, glamor->tex);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    glDisableVertexAttribArray(glamor->texture_shader_position_loc);
+    glDisableVertexAttribArray(glamor->texture_shader_texcoord_loc);
+
+    glXSwapBuffers(dpy, glamor->glx_win);
+}
+
+struct ephyr_glamor *
+ephyr_glamor_glx_screen_init(xcb_window_t win)
+{
+    GLXContext ctx;
+    struct ephyr_glamor *glamor;
+    GLXWindow glx_win;
+
+    glamor = calloc(1, sizeof(struct ephyr_glamor));
+    if (!glamor) {
+        FatalError("malloc");
+        return NULL;
+    }
+
+    glx_win = glXCreateWindow(dpy, fb_config, win, NULL);
+
+    ctx = glXCreateContext(dpy, visual_info, NULL, True);
+    if (ctx == NULL)
+        FatalError("glXCreateContext failed\n");
+
+    if (!glXMakeCurrent(dpy, glx_win, ctx))
+        FatalError("glXMakeCurrent failed\n");
+
+    glamor->ctx = ctx;
+    glamor->win = win;
+    glamor->glx_win = glx_win;
+    ephyr_glamor_setup_texturing_shader(glamor);
+
+    return glamor;
+}
+
+void
+ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor)
+{
+    glXMakeCurrent(dpy, None, NULL);
+    glXDestroyContext(dpy, glamor->ctx);
+    glXDestroyWindow(dpy, glamor->glx_win);
+
+    free(glamor);
+}
+
+xcb_visualtype_t *
+ephyr_glamor_get_visual(void)
+{
+    xcb_screen_t *xscreen =
+        xcb_aux_get_screen(XGetXCBConnection(dpy), DefaultScreen(dpy));
+    int attribs[] = {
+        GLX_RENDER_TYPE, GLX_RGBA_BIT,
+        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        GLX_RED_SIZE, 1,
+        GLX_GREEN_SIZE, 1,
+        GLX_BLUE_SIZE, 1,
+        GLX_DOUBLEBUFFER, 1,
+        None
+    };
+    int event_base = 0, error_base = 0, nelements;
+    GLXFBConfig *fbconfigs;
+
+    if (!glXQueryExtension (dpy, &error_base, &event_base))
+        FatalError("Couldn't find GLX extension\n");
+
+    fbconfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &nelements);
+    if (!nelements)
+        FatalError("Couldn't choose an FBConfig\n");
+    fb_config = fbconfigs[0];
+    free(fbconfigs);
+
+    visual_info = glXGetVisualFromFBConfig(dpy, fb_config);
+    if (visual_info == NULL)
+        FatalError("Couldn't get RGB visual\n");
+
+    return xcb_aux_find_visual_by_id(xscreen, visual_info->visualid);
+}
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.h b/hw/kdrive/ephyr/ephyr_glamor_glx.h
new file mode 100644
index 0000000..950beff
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2013 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.
+ */
+
+/**
+ * ephyr_glamor_glx.h
+ *
+ * Prototypes exposed by ephyr_glamor_glx.c, without including any
+ * server headers.
+ */
+
+#include <xcb/xcb.h>
+#include "dix-config.h"
+
+struct ephyr_glamor;
+struct pixman_region16;
+
+xcb_connection_t *
+ephyr_glamor_connect(void);
+
+void
+ephyr_glamor_set_texture(struct ephyr_glamor *ephyr_glamor, uint32_t tex);
+
+xcb_visualtype_t *
+ephyr_glamor_get_visual(void);
+
+struct ephyr_glamor *
+ephyr_glamor_glx_screen_init(xcb_window_t win);
+
+void
+ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor);
+
+#ifdef GLAMOR
+void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+                              struct pixman_region16 *damage);
+#else
+static inline void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+                              struct pixman_region16 *damage)
+{
+}
+#endif
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index 3230e70..807e717 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -35,6 +35,7 @@ extern Bool EphyrWantGrayScale;
 extern Bool EphyrWantResize;
 extern Bool kdHasPointer;
 extern Bool kdHasKbd;
+extern Bool ephyr_glamor;
 
 #ifdef GLXEXT
 extern Bool ephyrNoDRI;
@@ -138,6 +139,9 @@ ddxUseMsg(void)
     ErrorF("-fullscreen          Attempt to run Xephyr fullscreen\n");
     ErrorF("-grayscale           Simulate 8bit grayscale\n");
     ErrorF("-resizeable          Make Xephyr windows resizeable\n");
+#ifdef GLAMOR
+    ErrorF("-glamor              Enable 2D acceleration using glamor\n");
+#endif
     ErrorF
         ("-fakexa              Simulate acceleration using software rendering\n");
     ErrorF("-verbosity <level>   Set log verbosity level\n");
@@ -241,6 +245,16 @@ ddxProcessArgument(int argc, char **argv, int i)
         EphyrWantResize = 1;
         return 1;
     }
+#ifdef GLAMOR
+    else if (!strcmp (argv[i], "-glamor")) {
+        ephyr_glamor = TRUE;
+        ephyrFuncs.initAccel = ephyr_glamor_init;
+        ephyrFuncs.enableAccel = ephyr_glamor_enable;
+        ephyrFuncs.disableAccel = ephyr_glamor_disable;
+        ephyrFuncs.finiAccel = ephyr_glamor_fini;
+        return 1;
+    }
+#endif
     else if (!strcmp(argv[i], "-fakexa")) {
         ephyrFuncs.initAccel = ephyrDrawInit;
         ephyrFuncs.enableAccel = ephyrDrawEnable;
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 44ad8e2..19c2ed2 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -36,6 +36,7 @@
 #include <string.h>             /* for memset */
 #include <errno.h>
 #include <time.h>
+#include <err.h>
 
 #include <sys/ipc.h>
 #include <sys/shm.h>
@@ -54,6 +55,11 @@
 #include <xcb/xf86dri.h>
 #include <xcb/glx.h>
 #endif /* XF86DRI */
+#ifdef GLAMOR
+#include <epoxy/gl.h>
+#include "glamor.h"
+#include "ephyr_glamor_glx.h"
+#endif
 #include "ephyrlog.h"
 #include "ephyr.h"
 
@@ -90,6 +96,7 @@ extern Bool EphyrWantResize;
 char *ephyrResName = NULL;
 int ephyrResNameFromCmd = 0;
 char *ephyrTitle = NULL;
+Bool ephyr_glamor = FALSE;
 
 static void
  hostx_set_fullscreen_hint(void);
@@ -302,7 +309,10 @@ hostx_init(void)
         | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
 
     EPHYR_DBG("mark");
-    HostX.conn = xcb_connect(NULL, &HostX.screen);
+    if (ephyr_glamor)
+        HostX.conn = ephyr_glamor_connect();
+    else
+        HostX.conn = xcb_connect(NULL, &HostX.screen);
     if (xcb_connection_has_error(HostX.conn)) {
         fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
         exit(1);
@@ -312,7 +322,11 @@ hostx_init(void)
     HostX.winroot = xscreen->root;
     HostX.gc = xcb_generate_id(HostX.conn);
     HostX.depth = xscreen->root_depth;
-    HostX.visual  = xcb_aux_find_visual_by_id(xscreen, xscreen->root_visual);
+    if (ephyr_glamor) {
+        HostX.visual = ephyr_glamor_get_visual();
+    } else {
+        HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
+    }
 
     xcb_create_gc(HostX.conn, HostX.gc, HostX.winroot, 0, NULL);
     cookie_WINDOW_STATE = xcb_intern_atom(HostX.conn, FALSE,
@@ -642,7 +656,7 @@ hostx_screen_init(KdScreenInfo *screen,
         }
     }
 
-    if (HostX.have_shm) {
+    if (!ephyr_glamor && HostX.have_shm) {
         scrpriv->ximg = xcb_image_create_native(HostX.conn,
                                                 width,
                                                 buffer_height,
@@ -677,7 +691,7 @@ hostx_screen_init(KdScreenInfo *screen,
         }
     }
 
-    if (!shm_success) {
+    if (!ephyr_glamor && !shm_success) {
         EPHYR_DBG("Creating image %dx%d for screen scrpriv=%p\n",
                   width, buffer_height, scrpriv);
         scrpriv->ximg = xcb_image_create_native(HostX.conn,
@@ -711,7 +725,11 @@ hostx_screen_init(KdScreenInfo *screen,
     scrpriv->win_width = width;
     scrpriv->win_height = height;
 
-    if (host_depth_matches_server(scrpriv)) {
+    if (ephyr_glamor) {
+        *bytes_per_line = 0;
+        *bits_per_pixel = 0;
+        return NULL;
+    } else if (host_depth_matches_server(scrpriv)) {
         *bytes_per_line = scrpriv->ximg->stride;
         *bits_per_pixel = scrpriv->ximg->bpp;
 
@@ -742,6 +760,21 @@ hostx_paint_rect(KdScreenInfo *screen,
 
     EPHYR_DBG("painting in screen %d\n", scrpriv->mynum);
 
+    if (ephyr_glamor) {
+        BoxRec box;
+        RegionRec region;
+
+        box.x1 = dx;
+        box.y1 = dy;
+        box.x2 = dx + width;
+        box.y2 = dy + height;
+
+        RegionInit(&region, &box, 1);
+        ephyr_glamor_damage_redisplay(scrpriv->glamor, &region);
+        RegionUninit(&region);
+        return;
+    }
+
     /*
      *  Copy the image data updated by the shadow layer
      *  on to the window
@@ -1170,3 +1203,86 @@ hostx_get_resource_id_peer(int a_local_resource_id, int *a_remote_resource_id)
 }
 
 #endif                          /* XF86DRI */
+
+#ifdef GLAMOR
+Bool
+ephyr_glamor_init(ScreenPtr screen)
+{
+    KdScreenPriv(screen);
+    KdScreenInfo *kd_screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = kd_screen->driver;
+
+    scrpriv->glamor = ephyr_glamor_glx_screen_init(scrpriv->win);
+
+    glamor_init(screen,
+                GLAMOR_USE_SCREEN |
+                GLAMOR_USE_PICTURE_SCREEN |
+                GLAMOR_INVERTED_Y_AXIS);
+
+    return TRUE;
+}
+
+Bool
+ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
+{
+    KdScreenPriv(pScreen);
+    KdScreenInfo *kd_screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = kd_screen->driver;
+    PixmapPtr screen_pixmap;
+    uint32_t tex;
+
+    if (!ephyr_glamor)
+        return TRUE;
+
+    if (!glamor_glyphs_init(pScreen))
+        return FALSE;
+
+    /* kdrive's fbSetupScreen() told mi to have
+     * miCreateScreenResources() (which is called before this) make a
+     * scratch pixmap wrapping ephyr-glamor's NULL
+     * KdScreenInfo->fb.framebuffer.
+     *
+     * We want a real (texture-based) screen pixmap at this point.
+     * This is what glamor will render into, and we'll then texture
+     * out of that into the host's window to present the results.
+     *
+     * Thus, delete the current screen pixmap, and put a fresh one in.
+     */
+    screen_pixmap = pScreen->GetScreenPixmap(pScreen);
+    pScreen->DestroyPixmap(screen_pixmap);
+
+    screen_pixmap = pScreen->CreatePixmap(pScreen,
+                                          pScreen->width,
+                                          pScreen->height,
+                                          pScreen->rootDepth, 0);
+    pScreen->SetScreenPixmap(screen_pixmap);
+
+    /* Tell the GLX code what to GL texture to read from. */
+    tex = glamor_get_pixmap_texture(screen_pixmap);
+    ephyr_glamor_set_texture(scrpriv->glamor, tex);
+
+    return TRUE;
+}
+
+void
+ephyr_glamor_enable(ScreenPtr screen)
+{
+}
+
+void
+ephyr_glamor_disable(ScreenPtr screen)
+{
+}
+
+void
+ephyr_glamor_fini(ScreenPtr screen)
+{
+    KdScreenPriv(screen);
+    KdScreenInfo *kd_screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = kd_screen->driver;
+
+    glamor_fini(screen);
+    ephyr_glamor_glx_screen_fini(scrpriv->glamor);
+    scrpriv->glamor = NULL;
+}
+#endif
commit b634e909895f6001e7d9543e1350b20c82c8c01c
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Jun 27 23:56:23 2013 +0100

    hw/xwin: More closely follow ICCCM for setting input focus
    
    In multiwindow mode, more closely follow ICCCM section 4.1.7 when setting X
    input focus to a window when the native Windows window acquires input focus:
    
    - If InputHint is FALSE, don't use XSetInputFocus()
    - If the window supports the WM_TAKE_FOCUS protocol, send a WM_TAKE_FOCUS message
    
    This helps JDK 1.7 clients acquire the focus correctly.
    
    Also, factor out checking client support for a given WM_PROTOCOLS protocol as a
    separate function.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index c6da777..9f12521 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -111,6 +111,7 @@ typedef struct _WMInfo {
     WMMsgQueueRec wmMsgQueue;
     Atom atmWmProtos;
     Atom atmWmDelete;
+    Atom atmWmTakeFocus;
     Atom atmPrivMap;
     Bool fAllowOtherWM;
 } WMInfoRec, *WMInfoPtr;
@@ -453,6 +454,27 @@ GetWindowName(Display * pDisplay, Window iWin, char **ppWindowName)
 }
 
 /*
+ * Does the client support the specified WM_PROTOCOLS protocol?
+ */
+
+static Bool
+IsWmProtocolAvailable(Display * pDisplay, Window iWindow, Atom atmProtocol)
+{
+  int i, n, found = 0;
+  Atom *protocols;
+
+  if (XGetWMProtocols(pDisplay, iWindow, &protocols, &n)) {
+    for (i = 0; i < n; ++i)
+      if (protocols[i] == atmProtocol)
+        ++found;
+
+    XFree(protocols);
+  }
+
+  return found > 0;
+}
+
+/*
  * Send a message to the X server from the WM thread
  */
 
@@ -805,21 +827,10 @@ winMultiWindowWMProc(void *pArg)
             ErrorF("\tWM_WM_KILL\n");
 #endif
             {
-                int i, n, found = 0;
-                Atom *protocols;
-
-                /* --- */
-                if (XGetWMProtocols(pWMInfo->pDisplay,
-                                    pNode->msg.iWindow, &protocols, &n)) {
-                    for (i = 0; i < n; ++i)
-                        if (protocols[i] == pWMInfo->atmWmDelete)
-                            ++found;
-
-                    XFree(protocols);
-                }
-
                 /* --- */
-                if (found)
+                if (IsWmProtocolAvailable(pWMInfo->pDisplay,
+                                          pNode->msg.iWindow,
+                                          pWMInfo->atmWmDelete))
                     SendXMessage(pWMInfo->pDisplay,
                                  pNode->msg.iWindow,
                                  pWMInfo->atmWmProtos, pWMInfo->atmWmDelete);
@@ -832,11 +843,39 @@ winMultiWindowWMProc(void *pArg)
 #if CYGMULTIWINDOW_DEBUG
             ErrorF("\tWM_WM_ACTIVATE\n");
 #endif
-
             /* Set the input focus */
-            XSetInputFocus(pWMInfo->pDisplay,
-                           pNode->msg.iWindow,
-                           RevertToPointerRoot, CurrentTime);
+
+            /*
+               ICCCM 4.1.7 is pretty opaque, but it appears that the rules are
+               actually quite simple:
+               -- the WM_HINTS input field determines whether the WM should call
+               XSetInputFocus()
+               -- independently, the WM_TAKE_FOCUS protocol determines whether
+               the WM should send a WM_TAKE_FOCUS ClientMessage.
+            */
+            {
+              Bool neverFocus = FALSE;
+              XWMHints *hints = XGetWMHints(pWMInfo->pDisplay, pNode->msg.iWindow);
+
+              if (hints) {
+                if (hints->flags & InputHint)
+                  neverFocus = !hints->input;
+                XFree(hints);
+              }
+
+              if (!neverFocus)
+                XSetInputFocus(pWMInfo->pDisplay,
+                               pNode->msg.iWindow,
+                               RevertToPointerRoot, CurrentTime);
+
+              if (IsWmProtocolAvailable(pWMInfo->pDisplay,
+                                        pNode->msg.iWindow,
+                                        pWMInfo->atmWmTakeFocus))
+                SendXMessage(pWMInfo->pDisplay,
+                             pNode->msg.iWindow,
+                             pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus);
+
+            }
             break;
 
         case WM_WM_NAME_EVENT:
@@ -1404,6 +1443,8 @@ winInitMultiWindowWM(WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
                                        "WM_PROTOCOLS", False);
     pWMInfo->atmWmDelete = XInternAtom(pWMInfo->pDisplay,
                                        "WM_DELETE_WINDOW", False);
+    pWMInfo->atmWmTakeFocus = XInternAtom(pWMInfo->pDisplay,
+                                       "WM_TAKE_FOCUS", False);
 
     pWMInfo->atmPrivMap = XInternAtom(pWMInfo->pDisplay,
                                       WINDOWSWM_NATIVE_HWND, False);
commit 0fc84a2bb6970f6b05a19cd8b32a7f3f7fd148b3
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Feb 28 15:02:14 2014 +0000

    hw/xwin: Remove unnecessary casts from malloc/realloc/calloc calls
    
    Remove unnecessary casts from malloc/realloc/calloc calls. This is the style
    used for the majority of X server code.
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c
index f130651..6906114 100644
--- a/hw/xwin/glx/indirect.c
+++ b/hw/xwin/glx/indirect.c
@@ -1613,7 +1613,7 @@ glxWinCreateContext(__GLXscreen * screen,
         glxWinReleaseTexImage
     };
 
-    context = (__GLXWinContext *) calloc(1, sizeof(__GLXWinContext));
+    context = calloc(1, sizeof(__GLXWinContext));
 
     if (!context)
         return NULL;
diff --git a/hw/xwin/winallpriv.c b/hw/xwin/winallpriv.c
index cc3b3d1..629af92 100644
--- a/hw/xwin/winallpriv.c
+++ b/hw/xwin/winallpriv.c
@@ -58,7 +58,7 @@ winAllocatePrivates(ScreenPtr pScreen)
     }
 
     /* Allocate memory for the screen private structure */
-    pScreenPriv = (winPrivScreenPtr) malloc(sizeof(winPrivScreenRec));
+    pScreenPriv = malloc(sizeof(winPrivScreenRec));
     if (!pScreenPriv) {
         ErrorF("winAllocateScreenPrivates - malloc () failed\n");
         return FALSE;
@@ -150,7 +150,7 @@ winAllocateCmapPrivates(ColormapPtr pCmap)
     }
 
     /* Allocate memory for our private structure */
-    pCmapPriv = (winPrivCmapPtr) malloc(sizeof(winPrivCmapRec));
+    pCmapPriv = malloc(sizeof(winPrivCmapRec));
     if (!pCmapPriv) {
         ErrorF("winAllocateCmapPrivates - malloc () failed\n");
         return FALSE;
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboardxevents.c
index 226c3f0..7d3c30e 100644
--- a/hw/xwin/winclipboardxevents.c
+++ b/hw/xwin/winclipboardxevents.c
@@ -248,7 +248,7 @@ winClipboardFlushXEvents(HWND hwnd,
                                                       (LPCWSTR) pszGlobalData,
                                                       -1, NULL, 0, NULL, NULL);
                 /* NOTE: iConvertDataLen includes space for null terminator */
-                pszConvertData = (char *) malloc(iConvertDataLen);
+                pszConvertData = malloc(iConvertDataLen);
                 WideCharToMultiByte(CP_UTF8,
                                     0,
                                     (LPCWSTR) pszGlobalData,
@@ -581,8 +581,7 @@ winClipboardFlushXEvents(HWND hwnd,
                                                   pszReturnData, -1, NULL, 0);
 
                 /* Allocate memory for the Unicode string */
-                pwszUnicodeStr
-                    = (wchar_t *) malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
+                pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
                 if (!pwszUnicodeStr) {
                     ErrorF("winClipboardFlushXEvents - SelectionNotify "
                            "malloc failed for pwszUnicodeStr, aborting.\n");
diff --git a/hw/xwin/wincursor.c b/hw/xwin/wincursor.c
index a35336a..f3ac0f7 100644
--- a/hw/xwin/wincursor.c
+++ b/hw/xwin/wincursor.c
@@ -255,10 +255,8 @@ winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen)
         bi.bV4BlueMask = 0x000000FF;
         bi.bV4AlphaMask = 0xFF000000;
 
-        lpBits =
-            (uint32_t *) calloc(pScreenPriv->cursor.sm_cx *
-                                pScreenPriv->cursor.sm_cy,
-                                sizeof(uint32_t));
+        lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy,
+                        sizeof(uint32_t));
 
         if (lpBits) {
             int y;
@@ -302,9 +300,7 @@ winLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int screen)
         pbmiColors[2].rgbBlue = pCursor->foreBlue >> 8;
         pbmiColors[2].rgbReserved = 0;
 
-        lpBits =
-            (uint32_t *) calloc(pScreenPriv->cursor.sm_cx *
-                                pScreenPriv->cursor.sm_cy, sizeof(char));
+        lpBits = calloc(pScreenPriv->cursor.sm_cx * pScreenPriv->cursor.sm_cy, 1);
 
         pCur = (unsigned char *) lpBits;
         if (lpBits) {
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 1dd8ba5..c6da777 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -405,7 +405,7 @@ Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp)
 
         for (i = 0; i < nNum; i++)
             iLen += strlen(ppList[i]);
-        pszReturnData = (char *) malloc(iLen + 1);
+        pszReturnData = malloc(iLen + 1);
         pszReturnData[0] = '\0';
         for (i = 0; i < nNum; i++)
             strcat(pszReturnData, ppList[i]);
@@ -413,7 +413,7 @@ Xutf8TextPropertyToString(Display * pDisplay, XTextProperty * xtp)
             XFreeStringList(ppList);
     }
     else {
-        pszReturnData = (char *) malloc(1);
+        pszReturnData = malloc(1);
         pszReturnData[0] = '\0';
     }
 
@@ -537,7 +537,7 @@ UpdateName(WMInfoPtr pWMInfo, Window iWindow)
             int iLen =
                 MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1, NULL, 0);
             wchar_t *pwszWideWindowName =
-                (wchar_t *) malloc(sizeof(wchar_t) * (iLen + 1));
+                malloc(sizeof(wchar_t)*(iLen + 1));
             MultiByteToWideChar(CP_UTF8, 0, pszWindowName, -1,
                                 pwszWideWindowName, iLen);
 
@@ -1237,9 +1237,9 @@ winInitWM(void **ppWMInfo,
           pthread_mutex_t * ppmServerStarted,
           int dwScreen, HWND hwndScreen, BOOL allowOtherWM)
 {
-    WMProcArgPtr pArg = (WMProcArgPtr) malloc(sizeof(WMProcArgRec));
-    WMInfoPtr pWMInfo = (WMInfoPtr) malloc(sizeof(WMInfoRec));
-    XMsgProcArgPtr pXMsgArg = (XMsgProcArgPtr) malloc(sizeof(XMsgProcArgRec));
+    WMProcArgPtr pArg = malloc(sizeof(WMProcArgRec));
+    WMInfoPtr pWMInfo = malloc(sizeof(WMInfoRec));
+    XMsgProcArgPtr pXMsgArg = malloc(sizeof(XMsgProcArgRec));
 
     /* Bail if the input parameters are bad */
     if (pArg == NULL || pWMInfo == NULL || pXMsgArg == NULL) {
@@ -1432,7 +1432,7 @@ winSendMessageToWM(void *pWMInfo, winWMMessagePtr pMsg)
     ErrorF("winSendMessageToWM ()\n");
 #endif
 
-    pNode = (WMMsgNodePtr) malloc(sizeof(WMMsgNodeRec));
+    pNode = malloc(sizeof(WMMsgNodeRec));
     if (pNode != NULL) {
         memcpy(&pNode->msg, pMsg, sizeof(winWMMessageRec));
         PushMessage(&((WMInfoPtr) pWMInfo)->wmMsgQueue, pNode);
diff --git a/hw/xwin/winnativegdi.c b/hw/xwin/winnativegdi.c
index a2a5123..1859698 100644
--- a/hw/xwin/winnativegdi.c
+++ b/hw/xwin/winnativegdi.c
@@ -344,8 +344,7 @@ winCreateDIBNativeGDI(int iWidth, int iHeight, int iDepth,
     }
 
     /* Allocate bitmap info header */
-    pbmih = (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
-                                        + 256 * sizeof(RGBQUAD));
+    pbmih = malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
     if (pbmih == NULL) {
         ErrorF("winCreateDIBNativeGDI - malloc () failed\n");
         return FALSE;
diff --git a/hw/xwin/winprefslex.l b/hw/xwin/winprefslex.l
index 9af6103..fd13edc 100644
--- a/hw/xwin/winprefslex.l
+++ b/hw/xwin/winprefslex.l
@@ -45,7 +45,7 @@ extern void ErrorF (const char* /*f*/, ...);
 static char *makestr(char *str)
 {
   char *ptr;
-  ptr = (char*)malloc (strlen(str)+1);
+  ptr = malloc(strlen(str)+1);
   if (!ptr)
     {
       ErrorF ("winMultiWindowLex:makestr() out of memory\n");
diff --git a/hw/xwin/winprefsyacc.y b/hw/xwin/winprefsyacc.y
index 3b376b3..683fc44 100644
--- a/hw/xwin/winprefsyacc.y
+++ b/hw/xwin/winprefsyacc.y
@@ -311,10 +311,9 @@ static void
 AddMenuLine (char *text, MENUCOMMANDTYPE cmd, char *param)
 {
   if (menu.menuItem==NULL)
-    menu.menuItem = (MENUITEM*)malloc(sizeof(MENUITEM));
+    menu.menuItem = malloc(sizeof(MENUITEM));
   else
-    menu.menuItem = (MENUITEM*)
-      realloc(menu.menuItem, sizeof(MENUITEM)*(menu.menuItems+1));
+    menu.menuItem = realloc(menu.menuItem, sizeof(MENUITEM)*(menu.menuItems+1));
 
   strncpy (menu.menuItem[menu.menuItems].text, text, MENU_MAX);
   menu.menuItem[menu.menuItems].text[MENU_MAX] = 0;
@@ -339,10 +338,9 @@ CloseMenu (void)
     }
   
   if (pref.menuItems)
-    pref.menu = (MENUPARSED*)
-      realloc (pref.menu, (pref.menuItems+1)*sizeof(MENUPARSED));
+    pref.menu = realloc (pref.menu, (pref.menuItems+1)*sizeof(MENUPARSED));
   else
-    pref.menu = (MENUPARSED*)malloc (sizeof(MENUPARSED));
+    pref.menu = malloc (sizeof(MENUPARSED));
   
   memcpy (pref.menu+pref.menuItems, &menu, sizeof(MENUPARSED));
   pref.menuItems++;
@@ -365,10 +363,9 @@ static void
 AddIconLine (char *matchstr, char *iconfile)
 {
   if (pref.icon==NULL)
-    pref.icon = (ICONITEM*)malloc(sizeof(ICONITEM));
+    pref.icon = malloc(sizeof(ICONITEM));
   else
-    pref.icon = (ICONITEM*)
-      realloc(pref.icon, sizeof(ICONITEM)*(pref.iconItems+1));
+    pref.icon = realloc(pref.icon, sizeof(ICONITEM)*(pref.iconItems+1));
 
   strncpy(pref.icon[pref.iconItems].match, matchstr, MENU_MAX);
   pref.icon[pref.iconItems].match[MENU_MAX] = 0;
@@ -401,10 +398,9 @@ static void
 AddStyleLine (char *matchstr, unsigned long style)
 {
   if (pref.style==NULL)
-    pref.style = (STYLEITEM*)malloc(sizeof(STYLEITEM));
+    pref.style = malloc(sizeof(STYLEITEM));
   else
-    pref.style = (STYLEITEM*)
-      realloc(pref.style, sizeof(STYLEITEM)*(pref.styleItems+1));
+    pref.style = realloc(pref.style, sizeof(STYLEITEM)*(pref.styleItems+1));
 
   strncpy(pref.style[pref.styleItems].match, matchstr, MENU_MAX);
   pref.style[pref.styleItems].match[MENU_MAX] = 0;
@@ -434,10 +430,9 @@ static void
 AddSysMenuLine (char *matchstr, char *menuname, int pos)
 {
   if (pref.sysMenu==NULL)
-    pref.sysMenu = (SYSMENUITEM*)malloc(sizeof(SYSMENUITEM));
+    pref.sysMenu = malloc(sizeof(SYSMENUITEM));
   else
-    pref.sysMenu = (SYSMENUITEM*)
-      realloc(pref.sysMenu, sizeof(SYSMENUITEM)*(pref.sysMenuItems+1));
+    pref.sysMenu = realloc(pref.sysMenu, sizeof(SYSMENUITEM)*(pref.sysMenuItems+1));
 
   strncpy (pref.sysMenu[pref.sysMenuItems].match, matchstr, MENU_MAX);
   pref.sysMenu[pref.sysMenuItems].match[MENU_MAX] = 0;
diff --git a/hw/xwin/winshadgdi.c b/hw/xwin/winshadgdi.c
index 2e3c64c..5c815eb 100644
--- a/hw/xwin/winshadgdi.c
+++ b/hw/xwin/winshadgdi.c
@@ -184,8 +184,7 @@ winQueryRGBBitsAndMasks(ScreenPtr pScreen)
     }
 
     /* Allocate a bitmap header and color table */
-    pbmih = (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
-                                        + 256 * sizeof(RGBQUAD));
+    pbmih = malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
     if (pbmih == NULL) {
         ErrorF("winQueryRGBBitsAndMasks - malloc failed\n");
         return FALSE;
@@ -545,8 +544,7 @@ winInitScreenShadowGDI(ScreenPtr pScreen)
     pScreenPriv->hdcShadow = CreateCompatibleDC(pScreenPriv->hdcScreen);
 
     /* Allocate bitmap info header */
-    pScreenPriv->pbmih = (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
-                                                     + 256 * sizeof(RGBQUAD));
+    pScreenPriv->pbmih = malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
     if (pScreenPriv->pbmih == NULL) {
         ErrorF("winInitScreenShadowGDI - malloc () failed\n");
         return FALSE;
diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c
index 724976a..0b62696 100644
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -184,8 +184,8 @@ InitWin32RootlessEngine(win32RootlessWindowPtr pRLWinPriv)
 
     /* Allocate bitmap info header */
     pRLWinPriv->pbmihShadow =
-        (BITMAPINFOHEADER *) malloc(sizeof(BITMAPINFOHEADER)
-                                    + 256 * sizeof(RGBQUAD));
+        malloc(sizeof(BITMAPINFOHEADER)
+               + 256 * sizeof(RGBQUAD));
     if (pRLWinPriv->pbmihShadow == NULL) {
         ErrorF("InitWin32RootlessEngine - malloc () failed\n");
         return;
@@ -214,8 +214,7 @@ winMWExtWMCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
              newX, newY, pFrame->width, pFrame->height);
 #endif
 
-    pRLWinPriv =
-        (win32RootlessWindowPtr) malloc(sizeof(win32RootlessWindowRec));
+    pRLWinPriv = malloc(sizeof(win32RootlessWindowRec));
     pRLWinPriv->pFrame = pFrame;
     pRLWinPriv->pfb = NULL;
     pRLWinPriv->hbmpShadow = NULL;
diff --git a/hw/xwin/winwindow.c b/hw/xwin/winwindow.c
index 759aa5e..8c1c28f 100644
--- a/hw/xwin/winwindow.c
+++ b/hw/xwin/winwindow.c
@@ -155,7 +155,7 @@ winCopyWindowNativeGDI(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
     nbox = RegionNumRects(prgnDst);
 
     /* Allocate source points for each box */
-    if (!(pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec))))
+    if (!(pptSrc = malloc(nbox * sizeof(DDXPointRec))))
         return;
 
     /* Set an iterator pointer */
diff --git a/hw/xwin/winwindowswm.c b/hw/xwin/winwindowswm.c
index c3503db..2805ff7 100644
--- a/hw/xwin/winwindowswm.c
+++ b/hw/xwin/winwindowswm.c
@@ -162,7 +162,7 @@ ProcWindowsWMSelectInput(ClientPtr client)
         }
 
         /* build the entry */
-        pNewEvent = (WMEventPtr) malloc(sizeof(WMEventRec));
+        pNewEvent = malloc(sizeof(WMEventRec));
         if (!pNewEvent)
             return BadAlloc;
         pNewEvent->next = 0;
@@ -183,7 +183,7 @@ ProcWindowsWMSelectInput(ClientPtr client)
          * done through the resource database.
          */
         if (!pHead) {
-            pHead = (WMEventPtr *) malloc(sizeof(WMEventPtr));
+            pHead = malloc(sizeof(WMEventPtr));
             if (!pHead ||
                 !AddResource(eventResource, eventResourceType, (void *) pHead))
             {
commit 94f709cfce62e716f8d3adea388625850de71e78
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Feb 28 14:23:00 2014 +0000

    hw/xwin: Add missing FORCEEXIT token to XWin configuration file lexer
    
    Somehow this was left out of commmit f3fad371cce0f3836514ad5b29e59fa1ca0627a7
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winprefslex.l b/hw/xwin/winprefslex.l
index 15f7077..9af6103 100644
--- a/hw/xwin/winprefslex.l
+++ b/hw/xwin/winprefslex.l
@@ -90,6 +90,7 @@ ALWAYSONTOP             { return ALWAYSONTOP; }
 DEBUG                   { return DEBUGOUTPUT; }
 RELOAD                  { return RELOAD; }
 TRAYICON                { return TRAYICON; }
+FORCEEXIT		{ return FORCEEXIT; }
 SILENTEXIT		{ return SILENTEXIT; }
 "{"                     { return LB; }
 "}"                     { return RB; }
commit 6432d44020443bbda90bd46ffcb572b51be803a1
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Feb 28 14:21:46 2014 +0000

    hw/xwin: Silence bell when volume is zero
    
    Allow the bell to be turned off with X server option '-f 0', or by 'xset b off'.
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c
index b6b2086..3a75ab2 100644
--- a/hw/xwin/winkeybd.c
+++ b/hw/xwin/winkeybd.c
@@ -128,7 +128,7 @@ winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, void *pCtrl, int iClass)
      * sound on systems with a sound card or it will beep the PC speaker
      * on systems that do not have a sound card.
      */
-    MessageBeep(MB_OK);
+    if (iPercent > 0) MessageBeep(MB_OK);
 }
 
 /* Change some keyboard configuration parameters */
commit 7e37c4f727609d2d992ca46ffce56311c8d8225c
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Feb 28 14:21:06 2014 +0000

    hw/xwin: Fix typo in comment
    
    'i' before 'e' except after 'c'
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 304e6df..157006d 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -77,7 +77,7 @@ winInitClipboard(void)
 }
 
 /*
- * Create the Windows window that we use to recieve Windows messages
+ * Create the Windows window that we use to receive Windows messages
  */
 
 HWND
commit d75195b62677f5b0f17bbe089b3aea5b295d5f2c
Author: Colin Harrison <colin.harrison at virgin.net>
Date:   Fri Feb 28 14:20:48 2014 +0000

    hw/xwin: Align parameter names in prototypes with definition
    
    A follow up to commits 2d9123fd, 451c5d91 and efe96a17, which changed the
    parameter name in the definition from index to i, to fix shadowing index() but
    didn't adjust the prototype declaration.
    
    Signed-off-by: Colin Harrison <colin.harrison at virgin.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 0adb227..80fc504 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -751,7 +751,7 @@ Bool
  winAllocatePrivates(ScreenPtr pScreen);
 
 Bool
- winInitCmapPrivates(ColormapPtr pCmap, int index);
+ winInitCmapPrivates(ColormapPtr pCmap, int i);
 
 Bool
  winAllocateCmapPrivates(ColormapPtr pCmap);
@@ -1056,12 +1056,12 @@ Bool
  winScreenInit(ScreenPtr pScreen, int argc, char **argv);
 
 Bool
- winFinishScreenInitFB(int index, ScreenPtr pScreen, int argc, char **argv);
+ winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv);
 
 #if defined(XWIN_NATIVEGDI)
 Bool
 
-winFinishScreenInitNativeGDI(int index,
+winFinishScreenInitNativeGDI(int i,
                              ScreenPtr pScreen, int argc, char **argv);
 #endif
 
diff --git a/hw/xwin/winmonitors.h b/hw/xwin/winmonitors.h
index 8201e47..5fe3ecd 100644
--- a/hw/xwin/winmonitors.h
+++ b/hw/xwin/winmonitors.h
@@ -40,4 +40,4 @@ struct GetMonitorInfoData {
     HMONITOR monitorHandle;
 };
 
-Bool QueryMonitor(int index, struct GetMonitorInfoData *data);
+Bool QueryMonitor(int i, struct GetMonitorInfoData *data);
commit e53568e2c5004a434a16e3971fb2cd0823e6487b
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Jan 1 16:43:38 2014 +0000

    hw/xwin: Just generate the WGL wrappers we need
    
    Just generate the WGL wrappers we need, rather than for everything in wgl.xml
    
    This avoids generating a lot of unused wrappers, and also avoids compilation
    requiring a wglext.h at least as new as wgl.xml
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/glx/gen_gl_wrappers.py b/hw/xwin/glx/gen_gl_wrappers.py
index 683b9d9..cdbba63 100755
--- a/hw/xwin/glx/gen_gl_wrappers.py
+++ b/hw/xwin/glx/gen_gl_wrappers.py
@@ -43,35 +43,18 @@ thunkdefs=False
 staticwrappers=False
 nodebug=False
 
-#exclude base WGL API
-WinGDI={key: 1 for key in [
-     "wglCopyContext"
-    ,"wglCreateContext"
-    ,"wglCreateLayerContext"
-    ,"wglDeleteContext"
-    ,"wglGetCurrentContext"
-    ,"wglGetCurrentDC"
-    ,"wglGetProcAddress"
-    ,"wglMakeCurrent"
-    ,"wglShareLists"
-    ,"wglUseFontBitmapsA"
-    ,"wglUseFontBitmapsW"
-    ,"wglUseFontBitmaps"
-    ,"SwapBuffers"
-    ,"wglUseFontOutlinesA"
-    ,"wglUseFontOutlinesW"
-    ,"wglUseFontOutlines"
-    ,"wglDescribeLayerPlane"
-    ,"wglSetLayerPaletteEntries"
-    ,"wglGetLayerPaletteEntries"
-    ,"wglRealizeLayerPalette"
-    ,"wglSwapLayerBuffers"
-    ,"wglSwapMultipleBuffers"
-    ,"ChoosePixelFormat"
-    ,"DescribePixelFormat"
-    ,"GetEnhMetaFilePixelFormat"
-    ,"GetPixelFormat"
-    ,"SetPixelFormat"
+# list of WGL extension functions we use
+used_wgl_ext_fns = {key: 1 for key in [
+    "wglSwapIntervalEXT",
+    "wglGetExtensionsStringARB",
+    "wglDestroyPbufferARB",
+    "wglGetPbufferDCARB",
+    "wglReleasePbufferDCARB",
+    "wglCreatePbufferARB",
+    "wglMakeContextCurrentARB",
+    "wglChoosePixelFormatARB",
+    "wglGetPixelFormatAttribivARB",
+    "wglGetPixelFormatAttribivARB"
 ]}
 
 if __name__ == '__main__':
@@ -162,7 +145,7 @@ class PreResolveOutputGenerator(OutputGenerator):
     def genCmd(self, cmd, name):
         OutputGenerator.genCmd(self, cmd, name)
 
-        if name in WinGDI:
+        if prefix == 'wgl' and not name in used_wgl_ext_fns:
             return
 
         self.outFile.write('RESOLVE_DECL(PFN' + name.upper() + 'PROC);\n')
@@ -190,7 +173,7 @@ class WrapperOutputGenerator(OutputGenerator):
     def genCmd(self, cmd, name):
         OutputGenerator.genCmd(self, cmd, name)
 
-        if name in WinGDI:
+        if prefix == 'wgl' and not name in used_wgl_ext_fns:
             return
 
         proto=noneStr(cmd.elem.find('proto'))
commit dec5e9899bfee2a83f8a64f975790ecd2390256d
Author: Yaakov Selkowitz <yselkowitz at users.sourceforge.net>
Date:   Wed Apr 10 18:04:17 2013 +0100

    hw/xwin: Fix implicit-function-declaration warning in XwinExtensionInit() when compiled with XWIN_GLX_WINDOWS defined
    
    InitOutput.c: In function ‘XwinExtensionInit’:
    InitOutput.c:170:9: error: implicit declaration of function ‘glxWinPushNativeProvider’ [-Werror=implicit-function-declaration]
             glxWinPushNativeProvider();
             ^
    InitOutput.c:170:9: warning: nested extern declaration of ‘glxWinPushNativeProvider’ [-Wnested-externs]
    
    Signed-off-by: Yaakov Selkowitz <yselkowitz at users.sourceforge.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index b05ca27..9413350 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -58,8 +58,11 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
                                               HANDLE hToken,
                                               DWORD dwFlags, LPTSTR pszPath);
 #endif
-
 #include "glx_extinit.h"
+#ifdef XWIN_GLX_WINDOWS
+#include "glx/glwindows.h"
+#endif
+
 /*
  * References to external symbols
  */
commit bf3543739db18c6cd52908f7c693cb64f43e3f23
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Feb 1 13:21:15 2014 +0100

    xf86OpenSerial: Add support server managed fds
    
    Try to get a server managed fd from the Options before trying to open the
    device node ourselves.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/shared/posix_tty.c b/hw/xfree86/os-support/shared/posix_tty.c
index 4d08c1e..6e2af00 100644
--- a/hw/xfree86/os-support/shared/posix_tty.c
+++ b/hw/xfree86/os-support/shared/posix_tty.c
@@ -124,7 +124,11 @@ xf86OpenSerial(XF86OptionPtr options)
         return -1;
     }
 
-    SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
+    fd = xf86CheckIntOption(options, "fd", -1);
+
+    if (fd == -1)
+        SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
+
     if (fd == -1) {
         xf86Msg(X_ERROR,
                 "xf86OpenSerial: Cannot open device %s\n\t%s.\n",
commit d9a4059d400bf288aadd17c04885cb9b0fb93989
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jan 14 15:47:48 2014 +0100

    config-udev: Don't try to add drm devices twice
    
    Before this commit we were trying to add most drm devices twice, once
    from xf86platformProbe() and once from config_udev_init().
    
    This results in somewhat confusing messages in Xorg.log, ie:
    
    (II) xfree86: Adding drm device (/dev/dri/card0)
    Later followed by:
    (II) config/udev: Adding drm device (/dev/dri/card0)
    
    By filtering out duplicate drm devices we avoid these confusing messages.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/udev.c b/config/udev.c
index 2085185..d70eeb4 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -112,6 +112,10 @@ device_added(struct udev_device *udev_device)
         if (strncmp(sysname, "card", 4) != 0)
             return;
 
+        /* Check for devices already added through xf86platformProbe() */
+        if (xf86_find_platform_device_by_devnum(major(devnum), minor(devnum)))
+            return;
+
         LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
 
         config_udev_odev_setup_attribs(path, syspath, major(devnum),
commit 687afa3f6475060e6c460aa9496ba1a6a7982102
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Jan 31 15:21:38 2014 +0100

    systemd-logind: Add delayed input device probing
    
    With systemd-logind we cannot probe input devices while switched away, so
    if we're switched away, put the pInfo on a list, and probe everything on
    that list on VT-Enter.
    
    This is using an array grown by re-alloc, rather than a xorg_list since
    creating a new data-type to store a pInfo + list-entry just for this seems
    overkill.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 9d6b3ca..7c3e479 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -105,6 +105,9 @@
 static int
  xf86InputDevicePostInit(DeviceIntPtr dev);
 
+static InputInfoPtr *new_input_devices;
+static int new_input_devices_count;
+
 /**
  * Eval config and modify DeviceVelocityRec accordingly
  */
@@ -839,10 +842,20 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
     }
 
     if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
-        pInfo->fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
-                                           pInfo->attrs->device, &paused);
-        if (pInfo->fd != -1) {
-            /* FIXME handle paused */
+        int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
+                                        pInfo->attrs->device, &paused);
+        if (fd != -1) {
+            if (paused) {
+                /* Put on new_input_devices list for delayed probe */
+                new_input_devices = xnfrealloc(new_input_devices,
+                            sizeof(pInfo) * (new_input_devices_count + 1));
+                new_input_devices[new_input_devices_count] = pInfo;
+                new_input_devices_count++;
+                systemd_logind_release_fd(pInfo->major, pInfo->minor);
+                close(fd);
+                return BadMatch;
+            }
+            pInfo->fd = fd;
             pInfo->flags |= XI86_SERVER_FD;
             pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
         }
@@ -1493,4 +1506,32 @@ xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
     QueueTouchEvents(dev, type, touchid, flags, mask);
 }
 
+void
+xf86InputEnableVTProbe(void)
+{
+    int i, is_auto = 0;
+    InputOption *option = NULL;
+    DeviceIntPtr pdev;
+
+    for (i = 0; i < new_input_devices_count; i++) {
+        InputInfoPtr pInfo = new_input_devices[i];
+
+        is_auto = 0;
+        nt_list_for_each_entry(option, pInfo->options, list.next) {
+            const char *key = input_option_get_key(option);
+            const char *value = input_option_get_value(option);
+
+            if (strcmp(key, "_source") == 0 &&
+                (strcmp(value, "server/hal") == 0 ||
+                 strcmp(value, "server/udev") == 0 ||
+                 strcmp(value, "server/wscons") == 0))
+                is_auto = 1;
+        }
+        xf86NewInputDevice(pInfo, &pdev,
+                                  (!is_auto ||
+                                   (is_auto && xf86Info.autoEnableDevices)));
+    }
+    new_input_devices_count = 0;
+}
+
 /* end of xf86Xinput.c */
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 784e14e..9fe8c87 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -179,6 +179,7 @@ extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
 extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);
 extern _X_EXPORT void xf86DisableDevice(DeviceIntPtr dev, Bool panic);
 extern _X_EXPORT void xf86EnableDevice(DeviceIntPtr dev);
+extern _X_EXPORT void xf86InputEnableVTProbe(void);
 
 /* not exported */
 int xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL is_auto);
diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index 4732c08..abb8e44 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -198,6 +198,9 @@ systemd_logind_vtenter(void)
     for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
         if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
             xf86EnableInputDeviceForVTSwitch(pInfo);
+
+    /* Do delayed input probing, this must be done after the above enabling */
+    xf86InputEnableVTProbe();
 }
 
 static InputInfoPtr
commit cac39219898f5e5a59ff8d8d6524f5fe0d111469
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jan 14 15:37:33 2014 +0100

    systemd-logind: Hookup systemd-logind integration
    
    This commits makes the changes necessary outside of the systemd-logind core
    to make the server use systemd-logind managed fds for input devices and drm
    nodes.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index ea2f744..7971b87 100644
--- a/config/config.c
+++ b/config/config.c
@@ -27,10 +27,12 @@
 #include <dix-config.h>
 #endif
 
+#include <unistd.h>
 #include "os.h"
 #include "inputstr.h"
 #include "hotplug.h"
 #include "config-backends.h"
+#include "systemd-logind.h"
 
 void
 config_pre_init(void)
@@ -235,10 +237,21 @@ void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
     struct OdevAttribute *iter, *safe;
+    int major = 0, minor = 0, fd = -1;
 
     xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) {
+        switch (iter->attrib_id) {
+        case ODEV_ATTRIB_MAJOR: major = iter->attrib_value; break;
+        case ODEV_ATTRIB_MINOR: minor = iter->attrib_value; break;
+        case ODEV_ATTRIB_FD: fd = iter->attrib_value; break;
+        }
         xorg_list_del(&iter->member);
         free(iter->attrib_name);
         free(iter);
     }
+
+    if (fd != -1) {
+        systemd_logind_release_fd(major, minor);
+        close(fd);
+    }
 }
diff --git a/config/udev.c b/config/udev.c
index 68ed348..2085185 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -29,6 +29,7 @@
 
 #include <libudev.h>
 #include <ctype.h>
+#include <unistd.h>
 
 #include "input.h"
 #include "inputstr.h"
@@ -36,6 +37,7 @@
 #include "config-backends.h"
 #include "os.h"
 #include "globals.h"
+#include "systemd-logind.h"
 
 #define UDEV_XKB_PROP_KEY "xkb"
 
@@ -55,9 +57,18 @@ static struct udev_monitor *udev_monitor;
 #ifdef CONFIG_UDEV_KMS
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               int major, int minor,
                                config_odev_probe_proc_ptr probe_callback);
 #endif
 
+static char itoa_buf[16];
+
+static const char *itoa(int i)
+{
+    snprintf(itoa_buf, sizeof(itoa_buf), "%d", i);
+    return itoa_buf;
+}
+
 static void
 device_added(struct udev_device *udev_device)
 {
@@ -73,6 +84,7 @@ device_added(struct udev_device *udev_device)
     struct udev_device *parent;
     int rc;
     const char *dev_seat;
+    dev_t devnum;
 
     path = udev_device_get_devnode(udev_device);
 
@@ -91,6 +103,8 @@ device_added(struct udev_device *udev_device)
     if (!SeatId && strcmp(dev_seat, "seat0"))
         return;
 
+    devnum = udev_device_get_devnum(udev_device);
+
 #ifdef CONFIG_UDEV_KMS
     if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) {
         const char *sysname = udev_device_get_sysname(udev_device);
@@ -100,7 +114,8 @@ device_added(struct udev_device *udev_device)
 
         LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
 
-        config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), NewGPUDeviceRequest);
         return;
     }
 #endif
@@ -153,6 +168,8 @@ device_added(struct udev_device *udev_device)
     input_options = input_option_new(input_options, "name", name);
     input_options = input_option_new(input_options, "path", path);
     input_options = input_option_new(input_options, "device", path);
+    input_options = input_option_new(input_options, "major", itoa(major(devnum)));
+    input_options = input_option_new(input_options, "minor", itoa(minor(devnum)));
     if (path)
         attrs.device = strdup(path);
 
@@ -270,6 +287,7 @@ device_removed(struct udev_device *device)
     if (!strcmp(udev_device_get_subsystem(device), "drm")) {
         const char *sysname = udev_device_get_sysname(device);
         const char *path = udev_device_get_devnode(device);
+        dev_t devnum = udev_device_get_devnum(device);
 
         if (strncmp(sysname,"card", 4) != 0)
             return;
@@ -277,7 +295,10 @@ device_removed(struct udev_device *device)
         if (!path)
             return;
 
-        config_udev_odev_setup_attribs(path, syspath, DeleteGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), DeleteGPUDeviceRequest);
+        /* Retry vtenter after a drm node removal */
+        systemd_logind_vtenter();
         return;
     }
 #endif
@@ -427,6 +448,7 @@ config_udev_fini(void)
 
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               int major, int minor,
                                config_odev_probe_proc_ptr probe_callback)
 {
     struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
@@ -443,6 +465,14 @@ config_udev_odev_setup_attribs(const char *path, const char *syspath,
     if (ret == FALSE)
         goto fail;
 
+    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
+    if (ret == FALSE)
+        goto fail;
+
+    ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
+    if (ret == FALSE)
+        goto fail;
+
     /* ownership of attribs is passed to probe layer */
     probe_callback(attribs);
     return TRUE;
@@ -477,6 +507,7 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
         const char *path = udev_device_get_devnode(udev_device);
         const char *sysname = udev_device_get_sysname(udev_device);
+        dev_t devnum = udev_device_get_devnum(udev_device);
 
         if (!path || !syspath)
             goto no_probe;
@@ -485,8 +516,8 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         else if (strncmp(sysname, "card", 4) != 0)
             goto no_probe;
 
-        config_udev_odev_setup_attribs(path, syspath, probe_callback);
-
+        config_udev_odev_setup_attribs(path, syspath, major(devnum),
+                                       minor(devnum), probe_callback);
     no_probe:
         udev_device_unref(udev_device);
     }
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 7b53949..06af739 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -85,6 +85,8 @@
 #endif
 
 #include "xf86platformBus.h"
+#include "systemd-logind.h"
+
 /*
  * This is a toggling variable:
  *  FALSE = No VT switching keys have been pressed last time around
@@ -556,8 +558,11 @@ xf86VTEnter(void)
     /* Turn screen saver off when switching back */
     dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
 
-    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
-        xf86EnableInputDeviceForVTSwitch(pInfo);
+    /* If we use systemd-logind it will enable input devices for us */
+    if (!systemd_logind_controls_session())
+        for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+            xf86EnableInputDeviceForVTSwitch(pInfo);
+
     for (ih = InputHandlers; ih; ih = ih->next) {
         if (ih->is_input)
             xf86EnableInputHandler(ih);
@@ -589,10 +594,14 @@ xf86VTSwitch(void)
     /*
      * Since all screens are currently all in the same state it is sufficient
      * check the first.  This might change in future.
+     *
+     * VTLeave is always handled here (VT_PROCESS guarantees this is safe),
+     * if we use systemd_logind xf86VTEnter() gets called by systemd-logind.c
+     * once it has resumed all drm nodes.
      */
     if (xf86VTOwner())
         xf86VTLeave();
-    else
+    else if (!systemd_logind_controls_session())
         xf86VTEnter();
 }
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 7d13f75..9d6b3ca 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -63,6 +63,7 @@
 #include "mipointer.h"
 #include "extinit.h"
 #include "loaderProcs.h"
+#include "systemd-logind.h"
 
 #include "exevents.h"           /* AddInputDevice */
 #include "exglobals.h"
@@ -80,6 +81,7 @@
 
 #include <stdarg.h>
 #include <stdint.h>             /* for int64_t */
+#include <unistd.h>
 
 #include "mi.h"
 
@@ -773,6 +775,11 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
         /* Else the entry wasn't in the xf86InputDevs list (ignore this). */
     }
 
+    if (pInp->flags & XI86_SERVER_FD) {
+        systemd_logind_release_fd(pInp->major, pInp->minor);
+        close(pInp->fd);
+    }
+
     free((void *) pInp->driver);
     free((void *) pInp->name);
     xf86optionListFree(pInp->options);
@@ -816,6 +823,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
 {
     InputDriverPtr drv = NULL;
     DeviceIntPtr dev = NULL;
+    Bool paused;
     int rval;
 
     /* Memory leak for every attached device if we don't
@@ -830,6 +838,16 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
         goto unwind;
     }
 
+    if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
+        pInfo->fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
+                                           pInfo->attrs->device, &paused);
+        if (pInfo->fd != -1) {
+            /* FIXME handle paused */
+            pInfo->flags |= XI86_SERVER_FD;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+        }
+    }
+
     xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName,
             pInfo->name);
 
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index f4c4d12..109a9a7 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -18,16 +18,38 @@
 #include "xf86Bus.h"
 
 #include "hotplug.h"
+#include "systemd-logind.h"
 
 static Bool
 get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 {
     drmSetVersion sv;
     char *buf;
-    int fd;
+    int major, minor, fd;
     int err = 0;
+    Bool paused, server_fd = FALSE;
+
+    major = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MAJOR, 0);
+    minor = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MINOR, 0);
+
+    fd = systemd_logind_take_fd(major, minor, path, &paused);
+    if (fd != -1) {
+        if (paused) {
+            LogMessage(X_ERROR,
+                    "Error systemd-logind returned paused fd for drm node\n");
+            systemd_logind_release_fd(major, minor);
+            return FALSE;
+        }
+        if (!config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd)) {
+            systemd_logind_release_fd(major, minor);
+            return FALSE;
+        }
+        server_fd = TRUE;
+    }
+
+    if (fd == -1)
+        fd = open(path, O_RDWR, O_CLOEXEC);
 
-    fd = open(path, O_RDWR, O_CLOEXEC);
     if (fd == -1)
         return FALSE;
 
@@ -48,12 +70,16 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
             delayed_index = xf86_num_platform_devices - 1;
     }
 
+    if (server_fd)
+        xf86_platform_devices[delayed_index].flags |= XF86_PDEV_SERVER_FD;
+
     buf = drmGetBusid(fd);
     xf86_add_platform_device_attrib(delayed_index,
                                     ODEV_ATTRIB_BUSID, buf);
     drmFreeBusid(buf);
 out:
-    close(fd);
+    if (!server_fd)
+        close(fd);
     return (err == 0);
 }
 
commit 82863656ec449644cd34a86388ba40f36cea11e9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Jan 7 12:15:12 2014 +0100

    systemd-logind: Add systemd-logind "core"
    
    This commits add the bulk of the systemd-logind integration code, but does
    not hook it up yet other then calling its init and fini functions, which
    don't do that much.
    
    Note the configure bits check for udev since systemd-logind use will only be
    supported in combination with udev. Besides that it only checks for dbus
    since all communication with systemd-logind is happening over dbus, so
    no further libs are needed.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index 0fb2fc3..588ae59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -626,6 +626,7 @@ AC_ARG_ENABLE(clientids,      AS_HELP_STRING([--disable-clientids], [Build Xorg
 AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
 AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
 AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
+AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -901,6 +902,26 @@ if test "x$CONFIG_HAL" = xyes; then
 fi
 AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
 
+if test "x$SYSTEMD_LOGIND" = xauto; then
+        if test "x$HAVE_DBUS" = xyes -a "x$CONFIG_UDEV" = xyes ; then
+                SYSTEMD_LOGIND=yes
+        else
+                SYSTEMD_LOGIND=no
+        fi
+fi
+if test "x$SYSTEMD_LOGIND" = xyes; then
+        if ! test "x$HAVE_DBUS" = xyes; then
+                AC_MSG_ERROR([systemd-logind requested, but D-Bus is not installed.])
+        fi
+        if ! test "x$CONFIG_UDEV" = xyes ; then
+                AC_MSG_ERROR([systemd-logind is only supported in combination with udev configuration.])
+        fi
+
+        AC_DEFINE(SYSTEMD_LOGIND, 1, [Enable systemd-logind integration])
+        NEED_DBUS="yes"
+fi
+AM_CONDITIONAL(SYSTEMD_LOGIND, [test "x$SYSTEMD_LOGIND" = xyes])
+
 if test "x$NEED_DBUS" = xyes; then
         AC_DEFINE(NEED_DBUS, 1, [Enable D-Bus core])
 fi
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index ff4d38f..4579ff5 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -54,6 +54,7 @@
 #include "site.h"
 #include "mi.h"
 #include "dbus-core.h"
+#include "systemd-logind.h"
 
 #include "compiler.h"
 
@@ -458,6 +459,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
             DoShowOptions();
 
         dbus_core_init();
+        systemd_logind_init();
 
         /* Do a general bus probe.  This will be a PCI probe for x86 platforms */
         xf86BusProbe();
@@ -1062,6 +1064,7 @@ ddxGiveUp(enum ExitCode error)
     if (xorgHWOpenConsole)
         xf86CloseConsole();
 
+    systemd_logind_fini();
     dbus_core_fini();
 
     xf86CloseLog(error);
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index e1d7bd0..4447e19 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -52,7 +52,7 @@ int platformSlotClaimed;
 
 int xf86_num_platform_devices;
 
-static struct xf86_platform_device *xf86_platform_devices;
+struct xf86_platform_device *xf86_platform_devices;
 
 int
 xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned)
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 3e27d34..78b5a5b 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -36,12 +36,14 @@ struct xf86_platform_device {
 /* xf86_platform_device flags */
 #define XF86_PDEV_UNOWNED       0x01
 #define XF86_PDEV_SERVER_FD     0x02
+#define XF86_PDEV_PAUSED        0x04
 
 #ifdef XSERVER_PLATFORM_BUS
 int xf86platformProbe(void);
 int xf86platformProbeDev(DriverPtr drvp);
 
 extern int xf86_num_platform_devices;
+extern struct xf86_platform_device *xf86_platform_devices;
 
 extern char *
 xf86_get_platform_attrib(int index, int attrib_id);
diff --git a/hw/xfree86/os-support/linux/Makefile.am b/hw/xfree86/os-support/linux/Makefile.am
index 83e7e00..1686dc2 100644
--- a/hw/xfree86/os-support/linux/Makefile.am
+++ b/hw/xfree86/os-support/linux/Makefile.am
@@ -21,6 +21,11 @@ APM_SRCS = lnx_apm.c
 XORG_CFLAGS += -DHAVE_APM
 endif
 
+if SYSTEMD_LOGIND
+LOGIND_SRCS = systemd-logind.c
+XORG_CFLAGS += $(DBUS_CFLAGS)
+endif
+
 liblinux_la_SOURCES = lnx_init.c lnx_video.c \
                      lnx_agp.c lnx_kmod.c lnx_bell.c lnx_platform.c \
                      $(srcdir)/../shared/bios_mmap.c \
@@ -30,6 +35,7 @@ liblinux_la_SOURCES = lnx_init.c lnx_video.c \
 		     $(srcdir)/../shared/sigio.c \
                      $(ACPI_SRCS) \
                      $(APM_SRCS) \
+                     $(LOGIND_SRCS) \
                      $(PLATFORM_PCI_SUPPORT)
 
 AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(DIX_CFLAGS) $(XORG_CFLAGS) $(PLATFORM_DEFINES)
diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
new file mode 100644
index 0000000..4732c08
--- /dev/null
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright © 2013 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Hans de Goede <hdegoede at redhat.com>
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <dbus/dbus.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "os.h"
+#include "dbus-core.h"
+#include "xf86.h"
+#include "xf86platformBus.h"
+#include "xf86Xinput.h"
+
+#include "systemd-logind.h"
+
+#define DBUS_TIMEOUT 500 /* Wait max 0.5 seconds */
+
+struct systemd_logind_info {
+    DBusConnection *conn;
+    char *session;
+    Bool active;
+    Bool vt_active;
+};
+
+static struct systemd_logind_info logind_info;
+
+int
+systemd_logind_take_fd(int _major, int _minor, const char *path,
+                       Bool *paused_ret)
+{
+    struct systemd_logind_info *info = &logind_info;
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    dbus_int32_t major = _major;
+    dbus_int32_t minor = _minor;
+    dbus_bool_t paused;
+    int fd = -1;
+
+    if (!info->session || major == 0)
+        return -1;
+
+    /* logind does not support mouse devs (with evdev we don't need them) */
+    if (strstr(path, "mouse"))
+        return -1;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+            "org.freedesktop.login1.Session", "TakeDevice");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+                                       DBUS_TYPE_UINT32, &minor,
+                                       DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: failed to take device %s: %s\n",
+                   path, error.message);
+        goto cleanup;
+    }
+
+    if (!dbus_message_get_args(reply, &error,
+                               DBUS_TYPE_UNIX_FD, &fd,
+                               DBUS_TYPE_BOOLEAN, &paused,
+                               DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: TakeDevice %s: %s\n",
+                   path, error.message);
+        goto cleanup;
+    }
+
+    *paused_ret = paused;
+
+    LogMessage(X_INFO, "systemd-logind: got fd for %s %u:%u fd %d paused %d\n",
+               path, major, minor, fd, paused);
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+
+    return fd;
+}
+
+void
+systemd_logind_release_fd(int _major, int _minor)
+{
+    struct systemd_logind_info *info = &logind_info;
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    dbus_int32_t major = _major;
+    dbus_int32_t minor = _minor;
+
+    if (!info->session || major == 0)
+        return;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+            "org.freedesktop.login1.Session", "ReleaseDevice");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+                                       DBUS_TYPE_UINT32, &minor,
+                                       DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply)
+        LogMessage(X_ERROR, "systemd-logind: failed to release device: %s\n",
+                   error.message);
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+int
+systemd_logind_controls_session(void)
+{
+    return logind_info.session ? 1 : 0;
+}
+
+void
+systemd_logind_vtenter(void)
+{
+    struct systemd_logind_info *info = &logind_info;
+    InputInfoPtr pInfo;
+    int i;
+
+    if (!info->session)
+        return; /* Not using systemd-logind */
+
+    if (!info->active)
+        return; /* Session not active */
+
+    if (info->vt_active)
+        return; /* Already did vtenter */
+
+    for (i = 0; i < xf86_num_platform_devices; i++) {
+        if (xf86_platform_devices[i].flags & XF86_PDEV_PAUSED)
+            break;
+    }
+    if (i != xf86_num_platform_devices)
+        return; /* Some drm nodes are still paused wait for resume */
+
+    xf86VTEnter();
+    info->vt_active = TRUE;
+
+    /* Activate any input devices which were resumed before the drm nodes */
+    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+        if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
+            xf86EnableInputDeviceForVTSwitch(pInfo);
+}
+
+static InputInfoPtr
+systemd_logind_find_info_ptr_by_devnum(int major, int minor)
+{
+    InputInfoPtr pInfo;
+
+    for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+        if (pInfo->major == major && pInfo->minor == minor &&
+                (pInfo->flags & XI86_SERVER_FD))
+            return pInfo;
+
+    return NULL;
+}
+
+static void
+systemd_logind_ack_pause(struct systemd_logind_info *info,
+                         dbus_int32_t minor, dbus_int32_t major)
+{
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+            "org.freedesktop.login1.Session", "PauseDeviceComplete");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+                                       DBUS_TYPE_UINT32, &minor,
+                                       DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply)
+        LogMessage(X_ERROR, "systemd-logind: failed to ack pause: %s\n",
+                   error.message);
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+static DBusHandlerResult
+message_filter(DBusConnection * connection, DBusMessage * message, void *data)
+{
+    struct systemd_logind_info *info = data;
+    struct xf86_platform_device *pdev = NULL;
+    InputInfoPtr pInfo = NULL;
+    int ack = 0, pause = 0, fd = -1;
+    DBusError error;
+    dbus_int32_t major, minor;
+    char *pause_str;
+
+    if (strcmp(dbus_message_get_path(message), info->session) != 0)
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    dbus_error_init(&error);
+
+    if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
+                               "PauseDevice")) {
+        if (!dbus_message_get_args(message, &error,
+                               DBUS_TYPE_UINT32, &major,
+                               DBUS_TYPE_UINT32, &minor,
+                               DBUS_TYPE_STRING, &pause_str,
+                               DBUS_TYPE_INVALID)) {
+            LogMessage(X_ERROR, "systemd-logind: PauseDevice: %s\n",
+                       error.message);
+            dbus_error_free(&error);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+
+        if (strcmp(pause_str, "pause") == 0) {
+            pause = 1;
+            ack = 1;
+        }
+        else if (strcmp(pause_str, "force") == 0) {
+            pause = 1;
+        }
+        else if (strcmp(pause_str, "gone") == 0) {
+            /* Device removal is handled through udev */
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+        else {
+            LogMessage(X_WARNING, "systemd-logind: unknown pause type: %s\n",
+                       pause_str);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+    }
+    else if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
+                                    "ResumeDevice")) {
+        if (!dbus_message_get_args(message, &error,
+                                   DBUS_TYPE_UINT32, &major,
+                                   DBUS_TYPE_UINT32, &minor,
+                                   DBUS_TYPE_UNIX_FD, &fd,
+                                   DBUS_TYPE_INVALID)) {
+            LogMessage(X_ERROR, "systemd-logind: ResumeDevice: %s\n",
+                       error.message);
+            dbus_error_free(&error);
+            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        }
+    } else
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    LogMessage(X_INFO, "systemd-logind: got %s for %u:%u\n",
+               pause ? "pause" : "resume", major, minor);
+
+    pdev = xf86_find_platform_device_by_devnum(major, minor);        
+    if (!pdev)
+        pInfo = systemd_logind_find_info_ptr_by_devnum(major, minor);
+    if (!pdev && !pInfo) {
+        LogMessage(X_WARNING, "systemd-logind: could not find dev %u:%u\n",
+                   major, minor);
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+    if (pause) {
+        /* Our VT_PROCESS usage guarantees we've already given up the vt */
+        info->active = info->vt_active = FALSE;
+        /* Note the actual vtleave has already been handled by xf86Events.c */
+        if (pdev)
+            pdev->flags |= XF86_PDEV_PAUSED;
+        else {
+            close(pInfo->fd);
+            pInfo->fd = -1;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", -1);
+        }
+        if (ack)
+            systemd_logind_ack_pause(info, major, minor);
+    }
+    else {
+        /* info->vt_active gets set by systemd_logind_vtenter() */
+        info->active = TRUE;
+
+        if (pdev) {
+            pdev->flags &= ~XF86_PDEV_PAUSED;
+            systemd_logind_vtenter();
+        }
+        else {
+            pInfo->fd = fd;
+            pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+            if (info->vt_active)
+                xf86EnableInputDeviceForVTSwitch(pInfo);
+        }
+    }
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+connect_hook(DBusConnection *connection, void *data)
+{
+    struct systemd_logind_info *info = data;
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    dbus_int32_t arg;
+    char *session = NULL;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1",
+            "/org/freedesktop/login1", "org.freedesktop.login1.Manager",
+            "GetSessionByPID");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    arg = getpid();
+    if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &arg,
+                                  DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(connection, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: failed to get session: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+    dbus_message_unref(msg);
+
+    if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &session,
+                               DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: GetSessionByPID: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+    session = XNFstrdup(session);
+
+    dbus_message_unref(reply);
+    reply = NULL;
+
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1",
+            session, "org.freedesktop.login1.Session", "TakeControl");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    arg = FALSE; /* Don't forcibly take over over the session */
+    if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg,
+                                  DBUS_TYPE_INVALID)) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(connection, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: TakeControl failed: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
+    /*
+     * HdG: This is not useful with systemd <= 208 since the signal only
+     * contains invalidated property names there, rather than property, val
+     * pairs as it should.  Instead we just use the first resume / pause now.
+     */
+#if 0
+    snprintf(match, sizeof(match),
+        "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='%s'",
+        session);
+    dbus_bus_add_match(connection, match, &error);
+    if (dbus_error_is_set(&error)) {
+        LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+#endif
+
+    if (!dbus_connection_add_filter(connection, message_filter, info, NULL)) {
+        LogMessage(X_ERROR, "systemd-logind: could not add filter: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
+    LogMessage(X_INFO, "systemd-logind: took control of session %s\n",
+               session);
+    info->conn = connection;
+    info->session = session;
+    info->vt_active = info->active = TRUE; /* The server owns the vt during init */
+    session = NULL;
+
+cleanup:
+    free(session);
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+static void
+systemd_logind_release_control(struct systemd_logind_info *info)
+{
+    DBusError error;
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+
+    dbus_error_init(&error);
+
+    msg = dbus_message_new_method_call("org.freedesktop.login1",
+            info->session, "org.freedesktop.login1.Session", "ReleaseControl");
+    if (!msg) {
+        LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+        goto cleanup;
+    }
+
+    reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+                                                      DBUS_TIMEOUT, &error);
+    if (!reply) {
+        LogMessage(X_ERROR, "systemd-logind: ReleaseControl failed: %s\n",
+                   error.message);
+        goto cleanup;
+    }
+
+cleanup:
+    if (msg)
+        dbus_message_unref(msg);
+    if (reply)
+        dbus_message_unref(reply);
+    dbus_error_free(&error);
+}
+
+static void
+disconnect_hook(void *data)
+{
+    struct systemd_logind_info *info = data;
+
+    free(info->session);
+    info->session = NULL;
+    info->conn = NULL;
+}
+
+static struct dbus_core_hook core_hook = {
+    .connect = connect_hook,
+    .disconnect = disconnect_hook,
+    .data = &logind_info,
+};
+
+int
+systemd_logind_init(void)
+{
+    return dbus_core_add_hook(&core_hook);
+}
+
+void
+systemd_logind_fini(void)
+{
+    if (logind_info.session)
+        systemd_logind_release_control(&logind_info);
+
+    dbus_core_remove_hook(&core_hook);
+}
diff --git a/include/Makefile.am b/include/Makefile.am
index fa6da00..6578038 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -72,4 +72,5 @@ EXTRA_DIST = 	\
 	dix-config-apple-verbatim.h \
 	dixfontstubs.h eventconvert.h eventstr.h inpututils.h \
 	protocol-versions.h \
+	systemd-logind.h \
 	xsha1.h
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 7c77956..3865d5e 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -420,6 +420,9 @@
 /* Support HAL for hotplug */
 #undef CONFIG_HAL
 
+/* Enable systemd-logind integration */
+#undef SYSTEMD_LOGIND 1
+
 /* Have a monotonic clock from clock_gettime() */
 #undef MONOTONIC_CLOCK
 
diff --git a/include/systemd-logind.h b/include/systemd-logind.h
new file mode 100644
index 0000000..8b09081
--- /dev/null
+++ b/include/systemd-logind.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Hans de Goede <hdegoede at redhat.com>
+ */
+
+#ifndef SYSTEMD_LOGIND_H
+#define SYSTEMD_LOGIND_H
+
+#ifdef SYSTEMD_LOGIND
+int systemd_logind_init(void);
+void systemd_logind_fini(void);
+int systemd_logind_take_fd(int major, int minor, const char *path, Bool *paus);
+void systemd_logind_release_fd(int major, int minor);
+int systemd_logind_controls_session(void);
+void systemd_logind_vtenter(void);
+#else
+#define systemd_logind_init()
+#define systemd_logind_fini()
+#define systemd_logind_take_fd(major, minor, path) -1
+#define systemd_logind_release_fd(dev)
+#define systemd_logind_controls_session() 0
+#define systemd_logind_vtenter()
+#endif
+
+#endif
commit 5fb641a29bfb4a33da964e1e9af523f3472015c6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jan 13 12:03:46 2014 +0100

    hotplug: Extend OdevAttributes for server-managed fd support
    
    With systemd-logind support, the xserver, rather than the drivers will be
    responsible for opening/closing the fd for drm nodes.
    
    This commit adds a fd member to OdevAttributes to store the fd to pass it
    along to the driver.
    
    systemd-logind tracks devices by their chardev major + minor numbers, so
    also add OdevAttributes to store the major and minor.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 97d606a..e1d7bd0 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -128,6 +128,20 @@ xf86_get_platform_device_unowned(int index)
         TRUE : FALSE;
 }
 
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor)
+{
+    int i, attr_major, attr_minor;
+
+    for (i = 0; i < xf86_num_platform_devices; i++) {
+        attr_major = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MAJOR, 0);
+        attr_minor = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MINOR, 0);
+        if (attr_major == major && attr_minor == minor)
+            return &xf86_platform_devices[i];
+    }
+    return NULL;
+}
+
 /*
  * xf86IsPrimaryPlatform() -- return TRUE if primary device
  * is a platform device and it matches this one.
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 9a49260..3e27d34 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -35,6 +35,7 @@ struct xf86_platform_device {
 
 /* xf86_platform_device flags */
 #define XF86_PDEV_UNOWNED       0x01
+#define XF86_PDEV_SERVER_FD     0x02
 
 #ifdef XSERVER_PLATFORM_BUS
 int xf86platformProbe(void);
diff --git a/include/hotplug.h b/include/hotplug.h
index 0e78721..1d9364e 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -78,6 +78,12 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
 #define ODEV_ATTRIB_SYSPATH 2
 /* DRI-style bus id */
 #define ODEV_ATTRIB_BUSID 3
+/* Server managed FD */
+#define ODEV_ATTRIB_FD 4
+/* Major number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MAJOR 5
+/* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MINOR 6
 
 typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
 void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
@@ -88,4 +94,8 @@ void DeleteGPUDeviceRequest(struct OdevAttributes *attribs);
 #endif
 
 #define ServerIsNotSeat0() (SeatId && strcmp(SeatId, "seat0"))
+
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor);
+
 #endif                          /* HOTPLUG_H */
commit a8d802cb019da0549da57576ba0cc2cef1c8a98c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 2 13:54:33 2014 +0100

    OdevAttribute: Remove unowned flag from OdevAttributes head
    
    The OdevAttributes struct should just be a head of the attributes list, and
    not contain various unrelated flags. Instead add a flags field to
    struct xf86_platform_device and use that.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 96ac3b0..e8c24f2 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -80,7 +80,7 @@ typedef enum {
  * mask is 0xFFFF0000.
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
-#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(15, 0)
+#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(16, 0)
 #define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(8, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 7a9600a..97d606a 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -55,7 +55,7 @@ int xf86_num_platform_devices;
 static struct xf86_platform_device *xf86_platform_devices;
 
 int
-xf86_add_platform_device(struct OdevAttributes *attribs)
+xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned)
 {
     xf86_platform_devices = xnfrealloc(xf86_platform_devices,
                                    (sizeof(struct xf86_platform_device)
@@ -63,6 +63,8 @@ xf86_add_platform_device(struct OdevAttributes *attribs)
 
     xf86_platform_devices[xf86_num_platform_devices].attribs = attribs;
     xf86_platform_devices[xf86_num_platform_devices].pdev = NULL;
+    xf86_platform_devices[xf86_num_platform_devices].flags =
+        unowned ? XF86_PDEV_UNOWNED : 0;
 
     xf86_num_platform_devices++;
     return 0;
@@ -122,7 +124,8 @@ xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int att
 Bool
 xf86_get_platform_device_unowned(int index)
 {
-    return xf86_platform_devices[index].attribs->unowned;
+    return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ?
+        TRUE : FALSE;
 }
 
 /*
@@ -529,10 +532,10 @@ void xf86platformVTProbe(void)
     int i;
 
     for (i = 0; i < xf86_num_platform_devices; i++) {
-        if (xf86_platform_devices[i].attribs->unowned == FALSE)
+        if (!(xf86_platform_devices[i].flags & XF86_PDEV_UNOWNED))
             continue;
 
-        xf86_platform_devices[i].attribs->unowned = FALSE;
+        xf86_platform_devices[i].flags &= ~XF86_PDEV_UNOWNED;
         xf86PlatformReprobeDevice(i, xf86_platform_devices[i].attribs);
     }
 }
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index d764026..9a49260 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -30,8 +30,12 @@ struct xf86_platform_device {
     struct OdevAttributes *attribs;
     /* for PCI devices */
     struct pci_device *pdev;
+    int flags;
 };
 
+/* xf86_platform_device flags */
+#define XF86_PDEV_UNOWNED       0x01
+
 #ifdef XSERVER_PLATFORM_BUS
 int xf86platformProbe(void);
 int xf86platformProbeDev(DriverPtr drvp);
@@ -43,7 +47,7 @@ xf86_get_platform_attrib(int index, int attrib_id);
 extern int
 xf86_get_platform_int_attrib(int index, int attrib_id, int def);
 extern int
-xf86_add_platform_device(struct OdevAttributes *attribs);
+xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned);
 extern int
 xf86_remove_platform_device(int dev_index);
 extern Bool
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 4317209..f4c4d12 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -44,7 +44,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 
     /* for a delayed probe we've already added the device */
     if (delayed_index == -1) {
-            xf86_add_platform_device(attribs);
+            xf86_add_platform_device(attribs, FALSE);
             delayed_index = xf86_num_platform_devices - 1;
     }
 
@@ -142,8 +142,7 @@ xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
     if (!xf86VTOwner()) {
             /* if we don't currently own the VT then don't probe the device,
                just mark it as unowned for later use */
-            attribs->unowned = TRUE;
-            xf86_add_platform_device(attribs);
+            xf86_add_platform_device(attribs, TRUE);
             return;
     }
 
diff --git a/include/hotplug.h b/include/hotplug.h
index 4657669..0e78721 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -46,7 +46,6 @@ struct OdevAttribute {
 
 struct OdevAttributes {
     struct xorg_list list;
-    Bool unowned;
 };
 
 struct OdevAttributes *
commit bc9d17fb566d57eabe4a3372773654fcf6ae5b44
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 2 15:28:31 2014 +0100

    OdevAttribute: Add support for integer attributes
    
    Add a couple of new functions for dealing with storing integer values into
    OdevAttributes.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 776f1d8..ea2f744 100644
--- a/config/config.c
+++ b/config/config.c
@@ -172,6 +172,26 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
     oa->attrib_id = attrib;
     free(oa->attrib_name);
     oa->attrib_name = strdup(attrib_name);
+    oa->attrib_type = ODEV_ATTRIB_STRING;
+    xorg_list_append(&oa->member, &attribs->list);
+    return TRUE;
+}
+
+Bool
+config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
+                              int attrib_value)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib);
+    if (!oa)
+        oa = calloc(1, sizeof(struct OdevAttribute));
+    if (!oa)
+        return FALSE;
+
+    oa->attrib_id = attrib;
+    oa->attrib_value = attrib_value;
+    oa->attrib_type = ODEV_ATTRIB_INT;
     xorg_list_append(&oa->member, &attribs->list);
     return TRUE;
 }
@@ -185,9 +205,32 @@ config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id)
     if (!oa)
         return NULL;
 
+    if (oa->attrib_type != ODEV_ATTRIB_STRING) {
+        LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
+                   __func__, attrib_id);
+        return NULL;
+    }
     return oa->attrib_name;
 }
 
+int
+config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib_id, int def)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib_id);
+    if (!oa)
+        return def;
+
+    if (oa->attrib_type != ODEV_ATTRIB_INT) {
+        LogMessage(X_ERROR, "Error %s called for non integer attrib %d\n",
+                   __func__, attrib_id);
+        return def;
+    }
+
+    return oa->attrib_value;
+}
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 6d3816d..7a9600a 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -89,6 +89,12 @@ xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
     return config_odev_add_attribute(device->attribs, attrib_id, attrib_name);
 }
 
+Bool
+xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value)
+{
+    return config_odev_add_int_attribute(xf86_platform_devices[index].attribs, attrib_id, attrib_value);
+}
+
 char *
 xf86_get_platform_attrib(int index, int attrib_id)
 {
@@ -101,6 +107,18 @@ xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_
     return config_odev_get_attribute(device->attribs, attrib_id);
 }
 
+int
+xf86_get_platform_int_attrib(int index, int attrib_id, int def)
+{
+    return config_odev_get_int_attribute(xf86_platform_devices[index].attribs, attrib_id, def);
+}
+
+int
+xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def)
+{
+    return config_odev_get_int_attribute(device->attribs, attrib_id, def);
+}
+
 Bool
 xf86_get_platform_device_unowned(int index)
 {
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 4e17578..d764026 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -41,12 +41,16 @@ extern int xf86_num_platform_devices;
 extern char *
 xf86_get_platform_attrib(int index, int attrib_id);
 extern int
+xf86_get_platform_int_attrib(int index, int attrib_id, int def);
+extern int
 xf86_add_platform_device(struct OdevAttributes *attribs);
 extern int
 xf86_remove_platform_device(int dev_index);
 extern Bool
 xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
 extern Bool
+xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value);
+extern Bool
 xf86_get_platform_device_unowned(int index);
 
 extern int
@@ -56,6 +60,8 @@ xf86platformRemoveDevice(int index);
 
 extern _X_EXPORT char *
 xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id);
+extern _X_EXPORT int
+xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def);
 extern _X_EXPORT Bool
 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid);
 
diff --git a/include/hotplug.h b/include/hotplug.h
index ee7b7d7..4657669 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -32,10 +32,16 @@ extern _X_EXPORT void config_pre_init(void);
 extern _X_EXPORT void config_init(void);
 extern _X_EXPORT void config_fini(void);
 
+enum { ODEV_ATTRIB_STRING, ODEV_ATTRIB_INT };
+
 struct OdevAttribute {
     struct xorg_list member;
     int attrib_id;
-    char *attrib_name;
+    union {
+        char *attrib_name;
+        int attrib_value;
+    };
+    int attrib_type;
 };
 
 struct OdevAttributes {
@@ -56,6 +62,14 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
 char *
 config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
 
+Bool
+config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
+                              int attrib_value);
+
+int
+config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib,
+                              int def);
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs);
 
commit 350559dcdcd8b0de57801302e385e25debcb91f1
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Feb 3 15:47:35 2014 +0100

    OdevAttribute: config_odev_add_attribute: replace existing values
    
    If an attribute already exists replace its value rather than adding a
    duplicate attribute with the new value to the list.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 088bd5a..776f1d8 100644
--- a/config/config.c
+++ b/config/config.c
@@ -163,11 +163,14 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
 {
     struct OdevAttribute *oa;
 
-    oa = malloc(sizeof(struct OdevAttribute));
+    oa = config_odev_find_attribute(attribs, attrib);
+    if (!oa)
+        oa = calloc(1, sizeof(struct OdevAttribute));
     if (!oa)
         return FALSE;
 
     oa->attrib_id = attrib;
+    free(oa->attrib_name);
     oa->attrib_name = strdup(attrib_name);
     xorg_list_append(&oa->member, &attribs->list);
     return TRUE;
commit 10c64e80569bbd35e97916a067f553cab27454b5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sun Feb 2 11:25:34 2014 +0100

    OdevAttribute: Add config_odev_get_attribute helper
    
    Add a config_odev_get_attribute helper, and replace the diy looping over all
    the attributes done in various places with calls to this helper.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/config.c b/config/config.c
index 760cf19..088bd5a 100644
--- a/config/config.c
+++ b/config/config.c
@@ -145,6 +145,18 @@ config_odev_free_attribute_list(struct OdevAttributes *attribs)
     free(attribs);
 }
 
+static struct OdevAttribute *
+config_odev_find_attribute(struct OdevAttributes *attribs, int attrib_id)
+{
+    struct OdevAttribute *oa;
+
+    xorg_list_for_each_entry(oa, &attribs->list, member) {
+        if (oa->attrib_id == attrib_id)
+          return oa;
+    }
+    return NULL;
+}
+
 Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name)
@@ -161,6 +173,18 @@ config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
     return TRUE;
 }
 
+char *
+config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id)
+{
+    struct OdevAttribute *oa;
+
+    oa = config_odev_find_attribute(attribs, attrib_id);
+    if (!oa)
+        return NULL;
+
+    return oa->attrib_name;
+}
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 5875a91..6d3816d 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -92,26 +92,13 @@ xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
 char *
 xf86_get_platform_attrib(int index, int attrib_id)
 {
-    struct xf86_platform_device *device = &xf86_platform_devices[index];
-    struct OdevAttribute *oa;
-
-    xorg_list_for_each_entry(oa, &device->attribs->list, member) {
-        if (oa->attrib_id == attrib_id)
-            return oa->attrib_name;
-    }
-    return NULL;
+    return config_odev_get_attribute(xf86_platform_devices[index].attribs, attrib_id);
 }
 
 char *
 xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id)
 {
-    struct OdevAttribute *oa;
-
-    xorg_list_for_each_entry(oa, &device->attribs->list, member) {
-        if (oa->attrib_id == attrib_id)
-            return oa->attrib_name;
-    }
-    return NULL;
+    return config_odev_get_attribute(device->attribs, attrib_id);
 }
 
 Bool
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 1865b31..4317209 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -118,17 +118,11 @@ xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
 void
 xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
 {
-    struct OdevAttribute *attrib;
     int i;
     char *path = NULL;
     Bool ret;
 
-    xorg_list_for_each_entry(attrib, &attribs->list, member) {
-        if (attrib->attrib_id == ODEV_ATTRIB_PATH) {
-            path = attrib->attrib_name;
-            break;
-        }
-    }
+    path = config_odev_get_attribute(attribs, ODEV_ATTRIB_PATH);
     if (!path)
         goto out_free;
 
diff --git a/include/hotplug.h b/include/hotplug.h
index 29a22c4..ee7b7d7 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -53,6 +53,9 @@ Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name);
 
+char *
+config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
+
 void
 config_odev_free_attributes(struct OdevAttributes *attribs);
 
commit 3346166a6596115421702c1f7e2732215674ab8e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jan 13 11:57:38 2014 +0100

    xf86Xinput: Modify API for server-managed fd support
    
    With systemd-logind support, the xserver, rather than the drivers will be
    responsible for opening/closing the fd for input devices.
    
    This commit adds a new capabilities field to the InputDriverRec and a
    XI86_DRV_CAP_SERVER_FD flag for drivers to indicate that they support server
    managed fds.
    
    This commit adds a new XI86_SERVER_FD flag to indicate to drivers when the
    server is managing the fd and they should not open/close it. Note that even
    if drivers declare they support server managed fds there is no guarantee they
    will actually get them.
    
    Since this changes the input driver ABI, this commit bumps it.
    
    systemd-logind tracks devices by their chardev major + minor numbers, since
    we are breaking ABI anyways also add major and minor fields for easy storage /
    retrieval of these.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index b6ec19d..96ac3b0 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -81,7 +81,7 @@ typedef enum {
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
 #define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(15, 0)
-#define ABI_XINPUT_VERSION	SET_ABI_VERSION(20, 0)
+#define ABI_XINPUT_VERSION	SET_ABI_VERSION(21, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(8, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index f6f2b90..7d13f75 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -949,6 +949,12 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
                 goto unwind;
             }
         }
+
+        if (strcmp(key, "major") == 0)
+            pInfo->major = atoi(value);
+
+        if (strcmp(key, "minor") == 0)
+            pInfo->minor = atoi(value);
     }
 
     nt_list_for_each_entry(option, options, list.next) {
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index b6d1251..784e14e 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -64,6 +64,10 @@
 /* 0x08 is reserved for legacy XI86_SEND_DRAG_EVENTS, do not use for now */
 /* server-internal only */
 #define XI86_DEVICE_DISABLED    0x10    /* device was disabled before vt switch */
+#define XI86_SERVER_FD		0x20	/* fd is managed by xserver */
+
+/* Input device driver capabilities */
+#define XI86_DRV_CAP_SERVER_FD	0x01
 
 /* This holds the input driver entry and module information. */
 typedef struct _InputDriverRec {
@@ -76,6 +80,7 @@ typedef struct _InputDriverRec {
                     struct _InputInfoRec * pInfo, int flags);
     void *module;
     const char **default_options;
+    int capabilities;
 } InputDriverRec, *InputDriverPtr;
 
 /* This is to input devices what the ScrnInfoRec is to screens. */
@@ -96,6 +101,8 @@ typedef struct _InputInfoRec {
       int *valuators, int first_valuator, int num_valuators);
 
     int fd;
+    int major;
+    int minor;
     DeviceIntPtr dev;
     void *private;
     const char *type_name;
commit 6b79f28f5cb259f2168ecc3034fe2161e969bf7d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jan 22 11:32:56 2014 +0100

    linux: xf86OpenConsole: Don't detach from controlling tty when it is our vt
    
    Detaching from our controlling tty makes little sense when it is the same
    as the vt we're asked to run on. So automatically assume -keeptty in this case.
    
    This is useful to do because when not running as root the server can only make
    various VT related ioctls when it does not detach from the tty.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 9ccf261..85709c6 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -79,9 +79,10 @@ switch_to(int vt, const char *from)
 void
 xf86OpenConsole(void)
 {
-    int i, fd = -1, ret;
+    int i, fd = -1, ret, current_vt = -1;
     struct vt_mode VT;
     struct vt_stat vts;
+    struct stat st;
     MessageType from = X_PROBED;
     const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
     const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
@@ -126,6 +127,22 @@ xf86OpenConsole(void)
 
         xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
 
+        /* Some of stdin / stdout / stderr maybe redirected to a file */
+        for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+            ret = fstat(i, &st);
+            if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) {
+                current_vt = minor(st.st_rdev);
+                break;
+            }
+        }
+
+        if (!KeepTty && current_vt == xf86Info.vtno) {
+            xf86Msg(X_PROBED,
+                    "controlling tty is VT number %d, auto-enabling KeepTty\n",
+                    current_vt);
+            KeepTty = TRUE;
+        }
+
         if (!KeepTty) {
             pid_t ppid = getppid();
             pid_t ppgid;
commit 701b7ab34984b0f9f0c357b0ff8b53c5132c6324
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Jan 16 10:37:28 2014 +0100

    linux: xf86OpenConsole remove root-rights check for keeptty option
    
    There is no reason why keeptty cannot be used without root-rights.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 46438e6..9ccf261 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -87,12 +87,6 @@ xf86OpenConsole(void)
     const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
 
     if (serverGeneration == 1) {
-
-        /* when KeepTty check if we're run with euid==0 */
-        if (KeepTty && geteuid() != 0)
-            FatalError("xf86OpenConsole:"
-                       " Server must be suid root for option \"KeepTTY\"\n");
-
         /*
          * setup the virtual terminal manager
          */
commit caf1dec2a76fbbd21259fe4cc809e24a55ff79b4
Author: David Sodman <dsodman at chromium.org>
Date:   Mon Feb 10 09:07:33 2014 -0800

    V2: Add check for link from output to crtc before optimizing out a CrtcSet call
    
    The function RRCrtcSet call checks to see if the config being set is
    already configured, but, doesn't check that the selected outputs are
    connected to the crtc before skipping.  This means that the following
    sequence will omit the final CrtcSet call to the driver:
    
        CRTC c1 connect to output o
        CRTC c2 connect to output o
        CRTC c1 connect to output o
    
    This change adds the check to ensure that each of the calls are made to
    the driver.
    
    Signed-off-by: David Sodman <dsodman at chromium.org>
    Reviewed-by: Stéphane Marchesin <marcheu at chromium.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 6e181ba..6da698e 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -522,9 +522,19 @@ RRCrtcSet(RRCrtcPtr crtc,
     ScreenPtr pScreen = crtc->pScreen;
     Bool ret = FALSE;
     Bool recompute = TRUE;
+    Bool crtcChanged;
+    int  o;
 
     rrScrPriv(pScreen);
 
+    crtcChanged = FALSE;
+    for (o = 0; o < numOutputs; o++) {
+        if (outputs[o] && outputs[o]->crtc != crtc) {
+            crtcChanged = TRUE;
+            break;
+        }
+    }
+
     /* See if nothing changed */
     if (crtc->mode == mode &&
         crtc->x == x &&
@@ -532,7 +542,8 @@ RRCrtcSet(RRCrtcPtr crtc,
         crtc->rotation == rotation &&
         crtc->numOutputs == numOutputs &&
         !memcmp(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr)) &&
-        !RRCrtcPendingProperties(crtc) && !RRCrtcPendingTransform(crtc)) {
+        !RRCrtcPendingProperties(crtc) && !RRCrtcPendingTransform(crtc) &&
+        !crtcChanged) {
         recompute = FALSE;
         ret = TRUE;
     }
@@ -604,7 +615,6 @@ RRCrtcSet(RRCrtcPtr crtc,
 #endif
         }
         if (ret) {
-            int o;
 
             RRTellChanged(pScreen);
 
commit 249565a07d1d243e27440e2a5ecf4c95490903c6
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Feb 9 23:13:51 2014 -0800

    Fix test/os to work on Solaris
    
    Due to bad decisions made decades ago at AT&T, on SVR4 OS'es the signal()
    function resets the signal handler before calling the signal handler
    (equivalent to sigaction flag SA_RESETHAND).  This is why the X server
    has a OsSignal() helper function in os/utils.c that uses the portable
    POSIX sigaction function to provide BSD/Linux semantics in a signal()
    style API, so we switch to use that in this test case, allowing it to
    pass on Solaris.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/test/os.c b/test/os.c
index 2d005a0..d85dcff 100644
--- a/test/os.c
+++ b/test/os.c
@@ -150,10 +150,10 @@ static void block_sigio_test_nested(void)
        tail guard must be hit.
      */
     void (*old_handler)(int);
-    old_handler = signal(SIGIO, sighandler);
+    old_handler = OsSignal(SIGIO, sighandler);
     expect_signal = 1;
     assert(raise(SIGIO) == 0);
-    assert(signal(SIGIO, old_handler) == sighandler);
+    assert(OsSignal(SIGIO, old_handler) == sighandler);
 #endif
 }
 
commit 0031f6b073c7a4cca553c1d3e185a63436a75cbe
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Sun Feb 9 23:13:50 2014 -0800

    Fix test/signal-logging to work on Solaris
    
    For some reason, Solaris libc sprintf() doesn't add "0x" to the %p output
    as glibc does, causing the test to fail for not matching the exact output.
    Since the 0x is desirable, we add it ourselves to the test string.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/test/signal-logging.c b/test/signal-logging.c
index d894373..88b37c1 100644
--- a/test/signal-logging.c
+++ b/test/signal-logging.c
@@ -346,7 +346,11 @@ static void logging_format(void)
     ptr = 1;
     do {
         char expected[30];
+#ifdef __sun /* Solaris doesn't autoadd "0x" to %p format */
+        sprintf(expected, "(EE) 0x%p\n", (void*)ptr);
+#else
         sprintf(expected, "(EE) %p\n", (void*)ptr);
+#endif
         LogMessageVerbSigSafe(X_ERROR, -1, "%p\n", (void*)ptr);
         read_log_msg(logmsg);
         assert(strcmp(logmsg, expected) == 0);
commit e67f2d7e0f9189beb2907fa06cff5ecc7f35f922
Author: Matthieu Herrb <matthieu.herrb at laas.fr>
Date:   Sun Feb 9 11:20:59 2014 +0100

    gcc 4.2.1 doesn't support #pragma GCC diagnostic ignored
    
    Signed-off-by: Matthieu Herrb <matthieu at herrb.eu>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/os/log.c b/os/log.c
index 8deb810..38193ee 100644
--- a/os/log.c
+++ b/os/log.c
@@ -195,7 +195,9 @@ LogInit(const char *fname, const char *backup)
     char *logFileName = NULL;
 
     if (fname && *fname) {
+#if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 2
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
         if (asprintf(&logFileName, fname, display) == -1)
             FatalError("Cannot allocate space for the log file name\n");
 
@@ -206,7 +208,9 @@ LogInit(const char *fname, const char *backup)
                 char *suffix;
                 char *oldLog;
 
+#if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 2
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
                 if ((asprintf(&suffix, backup, display) == -1) ||
                     (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1))
                     FatalError("Cannot allocate space for the log file name\n");
commit 1940508a4af33d44a7a8ef24bbdcd1e31e228dab
Merge: c85ea92 ddeca92
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Feb 24 16:27:52 2014 -0800

    Merge remote-tracking branch 'herrb/master'

commit c85ea92af145c98a4a3fc6cf7b9eac796a48cc2e
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Feb 24 09:51:39 2014 -0800

    Bump to 1.15.99.901
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 4859dae..0fb2fc3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.15.99.900, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2014-01-09"
-RELEASE_NAME="Golden Gaytime"
+AC_INIT([xorg-server], 1.15.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2014-02-24"
+RELEASE_NAME="Szechuan Hot Pot"
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
commit 0840a303c47b9b10ba8e24e62956da0f1675e963
Merge: 0f10cfd 3d71df4
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Feb 24 09:40:23 2014 -0800

    Merge remote-tracking branch 'anholt/glamor-pull-request'

commit 0f10cfd4b903d4db293ec47c8a9a0d8b33965803
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Feb 20 13:18:05 2014 +1000

    Xi: check for invalid modifiers for XI2 passive grabs
    
    The other values are checked correctly, but if a modifier was outside the
    allowed range, it would go unnoticed and cause a out-of-bounds read error for
    any mask equal or larger than 256. The DetailRec where we store the grab masks
    is only sized to 8 * sizeof(Mask).
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4ed58ee..e9f670e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -2183,7 +2183,8 @@ CheckGrabValues(ClientPtr client, GrabParameters *param)
         return BadValue;
     }
 
-    if (param->grabtype != XI2 && (param->modifiers != AnyModifier) &&
+    if (param->modifiers != AnyModifier &&
+        param->modifiers != XIAnyModifier &&
         (param->modifiers & ~AllModifiersMask)) {
         client->errorValue = param->modifiers;
         return BadValue;
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index 8aba977..700622d 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -189,6 +189,10 @@ ProcXIPassiveGrabDevice(ClientPtr client)
         uint8_t status = Success;
 
         param.modifiers = *modifiers;
+        ret = CheckGrabValues(client, &param);
+        if (ret != Success)
+            goto out;
+
         switch (stuff->grab_type) {
         case XIGrabtypeButton:
             status = GrabButton(client, dev, mod_dev, stuff->detail,
commit ec6a44612565e0716bd5b2e2b80a8d381691feb6
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Wed Feb 19 13:48:06 2014 -0500

    test: remove source file from hashtabletest LDADD
    
    LDADD is for libraries and not for source code.
    
    Introduced in commit: 	ccb3e78124fb05defd0c9b438746b79d84dfc3ae
    
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/test/Makefile.am b/test/Makefile.am
index 2852bb3..f8aa659 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -36,7 +36,7 @@ fixes_LDADD=$(TEST_LDADD)
 xfree86_LDADD=$(TEST_LDADD)
 touch_LDADD=$(TEST_LDADD)
 signal_logging_LDADD=$(TEST_LDADD)
-hashtabletest_LDADD=$(TEST_LDADD) $(top_srcdir)/Xext/hashtable.c
+hashtabletest_LDADD=$(TEST_LDADD)
 os_LDADD=$(TEST_LDADD)
 
 libxservertest_la_LIBADD = $(XSERVER_LIBS)
commit 31b0be69e5eea3d1c82d6610bd37bbdb4dca779c
Author: Thierry Reding <treding at nvidia.com>
Date:   Wed Feb 19 17:16:48 2014 +0100

    test/input: Fix alignment assertion for doubles
    
    The code previously tried to compute the offset of a field in the
    valuator by subtracting the address of the valuator from the _value_ of
    the field (rather than the field's address). The correct way to do it
    would have been (note the &'s):
    
    	assert(((void *) &v->axisVal - (void *) v) % sizeof(double) == 0);
    	assert(((void *) &v->axes - (void *) v) % sizeof(double) == 0);
    
    That's essentially what the offsetof() macro does. Using offsetof() has
    the added benefit of not using void pointer arithmetic and therefore
    silencing a warning on some compilers.
    
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/test/input.c b/test/input.c
index 5813e6d..9b5db89 100644
--- a/test/input.c
+++ b/test/input.c
@@ -1390,8 +1390,8 @@ dix_valuator_alloc(void)
         assert(v->numAxes == num_axes);
 #if !defined(__i386__) && !defined(__m68k__) && !defined(__sh__)
         /* must be double-aligned on 64 bit */
-        assert(((void *) v->axisVal - (void *) v) % sizeof(double) == 0);
-        assert(((void *) v->axes - (void *) v) % sizeof(double) == 0);
+        assert(offsetof(struct _ValuatorClassRec, axisVal) % sizeof(double) == 0);
+        assert(offsetof(struct _ValuatorClassRec, axes) % sizeof(double) == 0);
 #endif
         num_axes++;
     }
commit 9368bdec1d37127e97411b684f0b1fce5ee97907
Author: Laércio de Sousa <lbsousajr at gmail.com>
Date:   Mon Feb 17 08:43:49 2014 +1000

    Get rid of config/non-seat0.conf.multi-seat
    
    This file is deprecated by commits c73c36b53 and 46cf2a6093.
    
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/config/Makefile.am b/config/Makefile.am
index c6350be..0e20e8b 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -38,4 +38,4 @@ endif # !CONFIG_HAL
 
 endif # !CONFIG_UDEV
 
-EXTRA_DIST = x11-input.fdi 10-evdev.conf non-seat0.conf.multi-seat fdi2iclass.py 10-quirks.conf
+EXTRA_DIST = x11-input.fdi 10-evdev.conf fdi2iclass.py 10-quirks.conf
diff --git a/config/non-seat0.conf.multi-seat b/config/non-seat0.conf.multi-seat
deleted file mode 100644
index 34008ce..0000000
--- a/config/non-seat0.conf.multi-seat
+++ /dev/null
@@ -1,18 +0,0 @@
-# This is the default configuration for servers on seat-1 and above.
-#
-# Start the server with -config non-seat0.conf.multi-seat, or alternatively
-# rename the file to end in .conf and put it in the standard config
-# directory (though it will apply to _all_ seats!).
-#
-# * Disable VT switching with Ctrl-Alt-F1
-# * Force a grab on all input devices to detach them from the VT subsystem
-#   to avoid event leakage.
-
-Section "ServerFlags"
-        Option "DontVTSwitch" "on"
-EndSection
-
-Section "InputClass"
-        Identifier "Force input devices to seat"
-        Option "GrabDevice" "on"
-EndSection
commit 3d71df48e70884deccb293cf1fcffbdba8efd94b
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 14:21:05 2013 -0800

    glamor: Move the EGL DRI3 code to GLAMOR_HAS_GBM.
    
    There's nothing dependent on the presence of DRI3 code in the server
    for this, but it does rely on GBM.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 81e697b..9dcba71 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -190,7 +190,7 @@ glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
     EGLImageKHR image;
     GLuint texture;
 
-#ifdef GLAMOR_HAS_DRI3_SUPPORT
+#ifdef GLAMOR_HAS_GBM
     struct gbm_bo *bo;
     EGLNativePixmapType native_pixmap;
 
@@ -356,7 +356,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
     return ret;
 }
 
-#ifdef GLAMOR_HAS_DRI3_SUPPORT
+#ifdef GLAMOR_HAS_GBM
 int glamor_get_fd_from_bo(int gbm_fd, struct gbm_bo *bo, int *fd);
 void glamor_get_name_from_bo(int gbm_fd, struct gbm_bo *bo, int *name);
 int
@@ -391,7 +391,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
                                  unsigned int tex,
                                  Bool want_name, CARD16 *stride, CARD32 *size)
 {
-#ifdef GLAMOR_HAS_DRI3_SUPPORT
+#ifdef GLAMOR_HAS_GBM
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_screen_private *glamor_priv =
         glamor_get_screen_private(screen);
@@ -460,7 +460,7 @@ glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
                                CARD16 height,
                                CARD16 stride, CARD8 depth, CARD8 bpp)
 {
-#ifdef GLAMOR_HAS_DRI3_SUPPORT
+#ifdef GLAMOR_HAS_GBM
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_egl_screen_private *glamor_egl;
     struct gbm_bo *bo;
@@ -735,7 +735,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
                                 KHR_surfaceless_opengl);
 #endif
 
-#ifdef GLAMOR_HAS_DRI3_SUPPORT
+#ifdef GLAMOR_HAS_GBM
     if (glamor_egl_has_extension(glamor_egl, "EGL_KHR_gl_texture_2D_image") &&
         glamor_egl_has_extension(glamor_egl, "EGL_EXT_image_dma_buf_import"))
         glamor_egl->dri3_capable = TRUE;
commit 80cdbb20f9dcdfdf3e77ecf5cdd7dfb1a87d1a83
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 13:21:21 2013 -0800

    glamor: Fix linking of the gradient shaders on GLES2.
    
    GLES2 sensibly doesn't allow you to attach multiple shaders for the
    same stage to a single program.  This means we have to attach the
    whole thing in one glShaderSource call.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 9ecaf03..9f6f1b1 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -42,14 +42,13 @@
 
 #ifdef GLAMOR_GRADIENT_SHADER
 
-static GLint
-_glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count,
-                                   int use_array)
+static const char *
+_glamor_create_getcolor_fs_source(ScreenPtr screen, int stops_count,
+                                  int use_array)
 {
     glamor_screen_private *glamor_priv;
 
     char *gradient_fs = NULL;
-    GLint fs_getcolor_prog;
 
 #define gradient_fs_getcolor\
 	    GLAMOR_DEFAULT_PRECISION\
@@ -181,17 +180,11 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count,
     if (use_array) {
         XNFasprintf(&gradient_fs,
                     gradient_fs_getcolor, stops_count, stops_count);
-        fs_getcolor_prog =
-            glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
-        free(gradient_fs);
+        return gradient_fs;
     }
     else {
-        fs_getcolor_prog =
-            glamor_compile_glsl_prog(GL_FRAGMENT_SHADER,
-                                     gradient_fs_getcolor_no_array);
+        return XNFstrdup(gradient_fs_getcolor_no_array);
     }
-
-    return fs_getcolor_prog;
 }
 
 static void
@@ -203,7 +196,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
 
     GLint gradient_prog = 0;
     char *gradient_fs = NULL;
-    GLint fs_main_prog, fs_getcolor_prog, vs_prog;
+    GLint fs_prog, vs_prog;
 
     const char *gradient_vs =
         GLAMOR_DEFAULT_PRECISION
@@ -344,7 +337,10 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
 	    "    } else {\n"\
 	    "        gl_FragColor = get_color(stop_len);\n"\
 	    "    }\n"\
-	    "}\n"
+	    "}\n"\
+	    "\n"\
+            "%s\n" /* fs_getcolor_source */
+    const char *fs_getcolor_source;
 
     glamor_priv = glamor_get_screen_private(screen);
 
@@ -364,25 +360,24 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
 
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, gradient_vs);
 
+    fs_getcolor_source =
+        _glamor_create_getcolor_fs_source(screen, stops_count,
+                                          (stops_count > 0));
+
     XNFasprintf(&gradient_fs,
                 gradient_radial_fs_template,
                 PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL,
-                PIXMAN_REPEAT_REFLECT);
+                PIXMAN_REPEAT_REFLECT,
+                fs_getcolor_source);
 
-    fs_main_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
 
     free(gradient_fs);
 
-    fs_getcolor_prog =
-        _glamor_create_getcolor_fs_program(screen, stops_count,
-                                           (stops_count > 0));
-
     glAttachShader(gradient_prog, vs_prog);
-    glAttachShader(gradient_prog, fs_getcolor_prog);
-    glAttachShader(gradient_prog, fs_main_prog);
+    glAttachShader(gradient_prog, fs_prog);
     glDeleteShader(vs_prog);
-    glDeleteShader(fs_getcolor_prog);
-    glDeleteShader(fs_main_prog);
+    glDeleteShader(fs_prog);
 
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
@@ -416,7 +411,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
     int index = 0;
     GLint gradient_prog = 0;
     char *gradient_fs = NULL;
-    GLint fs_main_prog, fs_getcolor_prog, vs_prog;
+    GLint fs_prog, vs_prog;
 
     const char *gradient_vs =
         GLAMOR_DEFAULT_PRECISION
@@ -559,7 +554,10 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
 	    "{\n"\
 	    "    float stop_len = get_stop_len();\n"\
 	    "    gl_FragColor = get_color(stop_len);\n"\
-	    "}\n"
+	    "}\n"\
+	    "\n"\
+            "%s" /* fs_getcolor_source */
+    const char *fs_getcolor_source;
 
     glamor_priv = glamor_get_screen_private(screen);
 
@@ -578,23 +576,21 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
 
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, gradient_vs);
 
+    fs_getcolor_source =
+        _glamor_create_getcolor_fs_source(screen, stops_count, stops_count > 0);
+
     XNFasprintf(&gradient_fs,
                 gradient_fs_template,
-                PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT);
+                PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT,
+                fs_getcolor_source);
 
-    fs_main_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
     free(gradient_fs);
 
-    fs_getcolor_prog =
-        _glamor_create_getcolor_fs_program(screen, stops_count,
-                                           (stops_count > 0));
-
     glAttachShader(gradient_prog, vs_prog);
-    glAttachShader(gradient_prog, fs_getcolor_prog);
-    glAttachShader(gradient_prog, fs_main_prog);
+    glAttachShader(gradient_prog, fs_prog);
     glDeleteShader(vs_prog);
-    glDeleteShader(fs_getcolor_prog);
-    glDeleteShader(fs_main_prog);
+    glDeleteShader(fs_prog);
 
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
commit 76bd0f994959f30a37d41eaf06f43f23c3b23faf
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 13:09:25 2013 -0800

    glamor: Don't bother keeping references to shader stages for gradients.
    
    They never get reattached to any other program, so saving them to
    unreference later is a waste of code.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 9460199..9ecaf03 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -356,20 +356,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
     glamor_get_context(glamor_priv);
 
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) {
-        glDeleteShader(glamor_priv->radial_gradient_shaders
-                       [SHADER_GRADIENT_VS_PROG][2]);
-        glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0;
-
-        glDeleteShader(glamor_priv->radial_gradient_shaders
-                       [SHADER_GRADIENT_FS_MAIN_PROG][2]);
-        glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] =
-            0;
-
-        glDeleteShader(glamor_priv->radial_gradient_shaders
-                       [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]);
-        glamor_priv->
-            radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0;
-
         glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]);
         glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0;
     }
@@ -394,6 +380,9 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
     glAttachShader(gradient_prog, vs_prog);
     glAttachShader(gradient_prog, fs_getcolor_prog);
     glAttachShader(gradient_prog, fs_main_prog);
+    glDeleteShader(vs_prog);
+    glDeleteShader(fs_getcolor_prog);
+    glDeleteShader(fs_main_prog);
 
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
@@ -414,13 +403,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
     }
 
     glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog;
-    glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] =
-        vs_prog;
-    glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] =
-        fs_main_prog;
-    glamor_priv->
-        radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] =
-        fs_getcolor_prog;
 
     glamor_put_context(glamor_priv);
 }
@@ -588,20 +570,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
 
     glamor_get_context(glamor_priv);
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) {
-        glDeleteShader(glamor_priv->linear_gradient_shaders
-                       [SHADER_GRADIENT_VS_PROG][2]);
-        glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0;
-
-        glDeleteShader(glamor_priv->linear_gradient_shaders
-                       [SHADER_GRADIENT_FS_MAIN_PROG][2]);
-        glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] =
-            0;
-
-        glDeleteShader(glamor_priv->linear_gradient_shaders
-                       [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]);
-        glamor_priv->
-            linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0;
-
         glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]);
         glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0;
     }
@@ -624,6 +592,9 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
     glAttachShader(gradient_prog, vs_prog);
     glAttachShader(gradient_prog, fs_getcolor_prog);
     glAttachShader(gradient_prog, fs_main_prog);
+    glDeleteShader(vs_prog);
+    glDeleteShader(fs_getcolor_prog);
+    glDeleteShader(fs_main_prog);
 
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
@@ -644,13 +615,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
     }
 
     glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog;
-    glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][index] =
-        vs_prog;
-    glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][index] =
-        fs_main_prog;
-    glamor_priv->
-        linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] =
-        fs_getcolor_prog;
 
     glamor_put_context(glamor_priv);
 }
@@ -665,18 +629,7 @@ glamor_init_gradient_shader(ScreenPtr screen)
 
     for (i = 0; i < 3; i++) {
         glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i] = 0;
-        glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0;
-        glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] =
-            0;
-        glamor_priv->
-            linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0;
-
         glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i] = 0;
-        glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i] = 0;
-        glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i] =
-            0;
-        glamor_priv->
-            radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i] = 0;
     }
     glamor_priv->linear_max_nstops = 0;
     glamor_priv->radial_max_nstops = 0;
@@ -699,39 +652,10 @@ glamor_fini_gradient_shader(ScreenPtr screen)
 
     for (i = 0; i < 3; i++) {
         /* Linear Gradient */
-        if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i])
-            glDeleteShader(glamor_priv->linear_gradient_shaders
-                           [SHADER_GRADIENT_VS_PROG][i]);
-
-        if (glamor_priv->
-            linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i])
-            glDeleteShader(glamor_priv->linear_gradient_shaders
-                           [SHADER_GRADIENT_FS_MAIN_PROG][i]);
-
-        if (glamor_priv->
-            linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i])
-            glDeleteShader(glamor_priv->linear_gradient_shaders
-                           [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]);
-
         if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i])
             glDeleteProgram(glamor_priv->gradient_prog
                             [SHADER_GRADIENT_LINEAR][i]);
 
-        /* Radial Gradient */
-        if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i])
-            glDeleteShader(glamor_priv->radial_gradient_shaders
-                           [SHADER_GRADIENT_VS_PROG][i]);
-
-        if (glamor_priv->
-            radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i])
-            glDeleteShader(glamor_priv->radial_gradient_shaders
-                           [SHADER_GRADIENT_FS_MAIN_PROG][i]);
-
-        if (glamor_priv->
-            radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i])
-            glDeleteShader(glamor_priv->radial_gradient_shaders
-                           [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]);
-
         if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i])
             glDeleteProgram(glamor_priv->gradient_prog
                             [SHADER_GRADIENT_RADIAL][i]);
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index e28a021..fe4b423 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -141,13 +141,6 @@ enum gradient_shader {
     SHADER_GRADIENT_COUNT,
 };
 
-enum gradient_shader_prog {
-    SHADER_GRADIENT_VS_PROG,
-    SHADER_GRADIENT_FS_MAIN_PROG,
-    SHADER_GRADIENT_FS_GETCOLOR_PROG,
-    SHADER_GRADIENT_PROG_COUNT,
-};
-
 struct glamor_screen_private;
 struct glamor_pixmap_private;
 
@@ -251,9 +244,7 @@ typedef struct glamor_screen_private {
     /* glamor gradient, 0 for small nstops, 1 for
        large nstops and 2 for dynamic generate. */
     GLint gradient_prog[SHADER_GRADIENT_COUNT][3];
-    GLint linear_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3];
     int linear_max_nstops;
-    GLint radial_gradient_shaders[SHADER_GRADIENT_PROG_COUNT][3];
     int radial_max_nstops;
 
     /* glamor trapezoid shader. */
commit 6e62cdf66d2f0baa4a26eff6f4917f73baf3b008
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 11:29:27 2013 -0800

    glamor: Fix typo in setting v_position's attrib location.
    
    Assuming it was the first attribute assigned by the GL, it would have
    ended up with location 0 anyway.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 4ea441e..9460199 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -395,7 +395,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
     glAttachShader(gradient_prog, fs_getcolor_prog);
     glAttachShader(gradient_prog, fs_main_prog);
 
-    glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_positionsition");
+    glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
     glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
 
     glamor_link_glsl_prog(gradient_prog);
commit f8d384fa8f0fa2a3ac04c4ad21fb04400490e8e6
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 02:13:27 2013 -0800

    glamor: Move shader precision stuff from build time to shader compile time.
    
    This is the last desktop-versus-ES2 build ifdef in core glamor.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 81b46b6..e28a021 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -37,11 +37,10 @@
 
 #include <epoxy/gl.h>
 
-#ifdef GLAMOR_GLES2
-#define GLAMOR_DEFAULT_PRECISION   "precision mediump float;\n"
-#else
-#define GLAMOR_DEFAULT_PRECISION
-#endif
+#define GLAMOR_DEFAULT_PRECISION  \
+    "#ifdef GL_ES\n"              \
+    "precision mediump float;\n"  \
+    "#endif\n"
 
 #ifdef RENDER
 #include "glyphstr.h"
commit 1adac62a7d9da099c779e65527ece611cf4d2f2c
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 02:10:53 2013 -0800

    glamor: Unifdef the picture-format-to-format-and-type functions.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 1dbeb04..77197b5 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -194,14 +194,13 @@ glamor_set_alu(ScreenPtr screen, unsigned char alu)
  *
  * Return 0 if find a matched texture type. Otherwise return -1.
  **/
-#ifndef GLAMOR_GLES2
 static int
-glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
-                                           GLenum *tex_format,
-                                           GLenum *tex_type,
-                                           int *no_alpha,
-                                           int *revert,
-                                           int *swap_rb, int is_upload)
+glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
+                                              GLenum *tex_format,
+                                              GLenum *tex_type,
+                                              int *no_alpha,
+                                              int *revert,
+                                              int *swap_rb, int is_upload)
 {
     *no_alpha = 0;
     *revert = REVERT_NONE;
@@ -291,16 +290,15 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
     return 0;
 }
 
-#else
 #define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
 
 static int
-glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
-                                           GLenum *tex_format,
-                                           GLenum *tex_type,
-                                           int *no_alpha,
-                                           int *revert,
-                                           int *swap_rb, int is_upload)
+glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format,
+                                                 GLenum *tex_format,
+                                                 GLenum *tex_type,
+                                                 int *no_alpha,
+                                                 int *revert,
+                                                 int *swap_rb, int is_upload)
 {
     int need_swap_rb = 0;
 
@@ -463,8 +461,6 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
     return 0;
 }
 
-#endif
-
 static int
 glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
                                        GLenum *format,
@@ -474,6 +470,8 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
 {
     glamor_pixmap_private *pixmap_priv;
     PictFormatShort pict_format;
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(pixmap->drawable.pScreen);
 
     pixmap_priv = glamor_get_pixmap_private(pixmap);
     if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
@@ -481,11 +479,21 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
     else
         pict_format = format_for_depth(pixmap->drawable.depth);
 
-    return glamor_get_tex_format_type_from_pictformat(pict_format,
-                                                      format, type,
-                                                      no_alpha,
-                                                      revert,
-                                                      swap_rb, is_upload);
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        return glamor_get_tex_format_type_from_pictformat_gl(pict_format,
+                                                             format, type,
+                                                             no_alpha,
+                                                             revert,
+                                                             swap_rb,
+                                                             is_upload);
+    } else {
+        return glamor_get_tex_format_type_from_pictformat_gles2(pict_format,
+                                                                format, type,
+                                                                no_alpha,
+                                                                revert,
+                                                                swap_rb,
+                                                                is_upload);
+    }
 }
 
 static void *
commit 3747c260816a36352bb91ce06befcbffbbd747c7
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 16:12:15 2013 -0800

    glamor: Move glamor_get_tex_format_type_from_pictformat to a .c file.
    
    A pair of 150 lines of inlined switch statements in a header file is
    crazy.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 30aeebe..1dbeb04 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -185,6 +185,309 @@ glamor_set_alu(ScreenPtr screen, unsigned char alu)
     return TRUE;
 }
 
+/*
+ * Map picture's format to the correct gl texture format and type.
+ * no_alpha is used to indicate whehter we need to wire alpha to 1.
+ *
+ * Although opengl support A1/GL_BITMAP, we still don't use it
+ * here, it seems that mesa has bugs when uploading a A1 bitmap.
+ *
+ * Return 0 if find a matched texture type. Otherwise return -1.
+ **/
+#ifndef GLAMOR_GLES2
+static int
+glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
+                                           GLenum *tex_format,
+                                           GLenum *tex_type,
+                                           int *no_alpha,
+                                           int *revert,
+                                           int *swap_rb, int is_upload)
+{
+    *no_alpha = 0;
+    *revert = REVERT_NONE;
+    *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
+    switch (format) {
+    case PICT_a1:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
+        break;
+    case PICT_b8g8r8x8:
+        *no_alpha = 1;
+    case PICT_b8g8r8a8:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_INT_8_8_8_8;
+        break;
+
+    case PICT_x8r8g8b8:
+        *no_alpha = 1;
+    case PICT_a8r8g8b8:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case PICT_x8b8g8r8:
+        *no_alpha = 1;
+    case PICT_a8b8g8r8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case PICT_x2r10g10b10:
+        *no_alpha = 1;
+    case PICT_a2r10g10b10:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
+        break;
+    case PICT_x2b10g10r10:
+        *no_alpha = 1;
+    case PICT_a2b10g10r10:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
+        break;
+
+    case PICT_r5g6b5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    case PICT_b5g6r5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV;
+        break;
+    case PICT_x1b5g5r5:
+        *no_alpha = 1;
+    case PICT_a1b5g5r5:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+
+    case PICT_x1r5g5b5:
+        *no_alpha = 1;
+    case PICT_a1r5g5b5:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+    case PICT_a8:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        break;
+    case PICT_x4r4g4b4:
+        *no_alpha = 1;
+    case PICT_a4r4g4b4:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+        break;
+
+    case PICT_x4b4g4r4:
+        *no_alpha = 1;
+    case PICT_a4b4g4r4:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+        break;
+
+    default:
+        LogMessageVerb(X_INFO, 0,
+                       "fail to get matched format for %x \n", format);
+        return -1;
+    }
+    return 0;
+}
+
+#else
+#define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
+
+static int
+glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
+                                           GLenum *tex_format,
+                                           GLenum *tex_type,
+                                           int *no_alpha,
+                                           int *revert,
+                                           int *swap_rb, int is_upload)
+{
+    int need_swap_rb = 0;
+
+    *no_alpha = 0;
+    *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
+
+    switch (format) {
+    case PICT_b8g8r8x8:
+        *no_alpha = 1;
+    case PICT_b8g8r8a8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        need_swap_rb = 1;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
+        break;
+
+    case PICT_x8r8g8b8:
+        *no_alpha = 1;
+    case PICT_a8r8g8b8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        need_swap_rb = 1;
+        break;
+
+    case PICT_x8b8g8r8:
+        *no_alpha = 1;
+    case PICT_a8b8g8r8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        break;
+
+    case PICT_x2r10g10b10:
+        *no_alpha = 1;
+    case PICT_a2r10g10b10:
+        *tex_format = GL_RGBA;
+        /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2.
+         * we have to use GL_UNSIGNED_BYTE and do the conversion in
+         * shader latter.*/
+        *tex_type = GL_UNSIGNED_BYTE;
+        if (is_upload == 1) {
+            if (!IS_LITTLE_ENDIAN)
+                *revert = REVERT_UPLOADING_10_10_10_2;
+            else
+                *revert = REVERT_UPLOADING_2_10_10_10;
+        }
+        else {
+            if (!IS_LITTLE_ENDIAN) {
+                *revert = REVERT_DOWNLOADING_10_10_10_2;
+            }
+            else {
+                *revert = REVERT_DOWNLOADING_2_10_10_10;
+            }
+        }
+        need_swap_rb = 1;
+
+        break;
+
+    case PICT_x2b10g10r10:
+        *no_alpha = 1;
+    case PICT_a2b10g10r10:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        if (is_upload == 1) {
+            if (!IS_LITTLE_ENDIAN)
+                *revert = REVERT_UPLOADING_10_10_10_2;
+            else
+                *revert = REVERT_UPLOADING_2_10_10_10;
+        }
+        else {
+            if (!IS_LITTLE_ENDIAN) {
+                *revert = REVERT_DOWNLOADING_10_10_10_2;
+            }
+            else {
+                *revert = REVERT_DOWNLOADING_2_10_10_10;
+            }
+        }
+        break;
+
+    case PICT_r5g6b5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
+
+        break;
+
+    case PICT_b5g6r5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
+        need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;;
+        break;
+
+    case PICT_x1b5g5r5:
+        *no_alpha = 1;
+    case PICT_a1b5g5r5:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
+        if (IS_LITTLE_ENDIAN) {
+            *revert =
+                is_upload ? REVERT_UPLOADING_1_5_5_5 :
+                REVERT_DOWNLOADING_1_5_5_5;
+        }
+        else
+            *revert = REVERT_NONE;
+        break;
+
+    case PICT_x1r5g5b5:
+        *no_alpha = 1;
+    case PICT_a1r5g5b5:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
+        if (IS_LITTLE_ENDIAN) {
+            *revert =
+                is_upload ? REVERT_UPLOADING_1_5_5_5 :
+                REVERT_DOWNLOADING_1_5_5_5;
+        }
+        else
+            *revert = REVERT_NONE;
+        need_swap_rb = 1;
+        break;
+
+    case PICT_a1:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
+        break;
+
+    case PICT_a8:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        *revert = REVERT_NONE;
+        break;
+
+    case PICT_x4r4g4b4:
+        *no_alpha = 1;
+    case PICT_a4r4g4b4:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
+        need_swap_rb = 1;
+        break;
+
+    case PICT_x4b4g4r4:
+        *no_alpha = 1;
+    case PICT_a4b4g4r4:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
+        break;
+
+    default:
+        LogMessageVerb(X_INFO, 0,
+                       "fail to get matched format for %x \n", format);
+        return -1;
+    }
+
+    if (need_swap_rb)
+        *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING;
+    else
+        *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
+    return 0;
+}
+
+#endif
+
+static int
+glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
+                                       GLenum *format,
+                                       GLenum *type,
+                                       int *no_alpha,
+                                       int *revert, int *swap_rb, int is_upload)
+{
+    glamor_pixmap_private *pixmap_priv;
+    PictFormatShort pict_format;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
+        pict_format = pixmap_priv->base.picture->format;
+    else
+        pict_format = format_for_depth(pixmap->drawable.depth);
+
+    return glamor_get_tex_format_type_from_pictformat(pict_format,
+                                                      format, type,
+                                                      no_alpha,
+                                                      revert,
+                                                      swap_rb, is_upload);
+}
+
 static void *
 _glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h,
                             int stride, int revert)
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index 3de6133..9374c9d 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -914,286 +914,6 @@ format_for_pixmap(PixmapPtr pixmap)
 #define SWAP_UPLOADING	  	2
 #define SWAP_NONE_UPLOADING	3
 
-/*
- * Map picture's format to the correct gl texture format and type.
- * no_alpha is used to indicate whehter we need to wire alpha to 1.
- *
- * Although opengl support A1/GL_BITMAP, we still don't use it
- * here, it seems that mesa has bugs when uploading a A1 bitmap.
- *
- * Return 0 if find a matched texture type. Otherwise return -1.
- **/
-#ifndef GLAMOR_GLES2
-static inline int
-glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
-                                           GLenum * tex_format,
-                                           GLenum * tex_type,
-                                           int *no_alpha,
-                                           int *revert,
-                                           int *swap_rb, int is_upload)
-{
-    *no_alpha = 0;
-    *revert = REVERT_NONE;
-    *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
-    switch (format) {
-    case PICT_a1:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
-        break;
-    case PICT_b8g8r8x8:
-        *no_alpha = 1;
-    case PICT_b8g8r8a8:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_INT_8_8_8_8;
-        break;
-
-    case PICT_x8r8g8b8:
-        *no_alpha = 1;
-    case PICT_a8r8g8b8:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
-        break;
-    case PICT_x8b8g8r8:
-        *no_alpha = 1;
-    case PICT_a8b8g8r8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
-        break;
-    case PICT_x2r10g10b10:
-        *no_alpha = 1;
-    case PICT_a2r10g10b10:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
-        break;
-    case PICT_x2b10g10r10:
-        *no_alpha = 1;
-    case PICT_a2b10g10r10:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
-        break;
-
-    case PICT_r5g6b5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
-        break;
-    case PICT_b5g6r5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV;
-        break;
-    case PICT_x1b5g5r5:
-        *no_alpha = 1;
-    case PICT_a1b5g5r5:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
-        break;
-
-    case PICT_x1r5g5b5:
-        *no_alpha = 1;
-    case PICT_a1r5g5b5:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
-        break;
-    case PICT_a8:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        break;
-    case PICT_x4r4g4b4:
-        *no_alpha = 1;
-    case PICT_a4r4g4b4:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
-        break;
-
-    case PICT_x4b4g4r4:
-        *no_alpha = 1;
-    case PICT_a4b4g4r4:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
-        break;
-
-    default:
-        LogMessageVerb(X_INFO, 0,
-                       "fail to get matched format for %x \n", format);
-        return -1;
-    }
-    return 0;
-}
-
-#else
-#define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
-
-static inline int
-glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
-                                           GLenum * tex_format,
-                                           GLenum * tex_type,
-                                           int *no_alpha,
-                                           int *revert,
-                                           int *swap_rb, int is_upload)
-{
-    int need_swap_rb = 0;
-
-    *no_alpha = 0;
-    *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
-
-    switch (format) {
-    case PICT_b8g8r8x8:
-        *no_alpha = 1;
-    case PICT_b8g8r8a8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        need_swap_rb = 1;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
-        break;
-
-    case PICT_x8r8g8b8:
-        *no_alpha = 1;
-    case PICT_a8r8g8b8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        need_swap_rb = 1;
-        break;
-
-    case PICT_x8b8g8r8:
-        *no_alpha = 1;
-    case PICT_a8b8g8r8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        break;
-
-    case PICT_x2r10g10b10:
-        *no_alpha = 1;
-    case PICT_a2r10g10b10:
-        *tex_format = GL_RGBA;
-        /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2.
-         * we have to use GL_UNSIGNED_BYTE and do the conversion in
-         * shader latter.*/
-        *tex_type = GL_UNSIGNED_BYTE;
-        if (is_upload == 1) {
-            if (!IS_LITTLE_ENDIAN)
-                *revert = REVERT_UPLOADING_10_10_10_2;
-            else
-                *revert = REVERT_UPLOADING_2_10_10_10;
-        }
-        else {
-            if (!IS_LITTLE_ENDIAN) {
-                *revert = REVERT_DOWNLOADING_10_10_10_2;
-            }
-            else {
-                *revert = REVERT_DOWNLOADING_2_10_10_10;
-            }
-        }
-        need_swap_rb = 1;
-
-        break;
-
-    case PICT_x2b10g10r10:
-        *no_alpha = 1;
-    case PICT_a2b10g10r10:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        if (is_upload == 1) {
-            if (!IS_LITTLE_ENDIAN)
-                *revert = REVERT_UPLOADING_10_10_10_2;
-            else
-                *revert = REVERT_UPLOADING_2_10_10_10;
-        }
-        else {
-            if (!IS_LITTLE_ENDIAN) {
-                *revert = REVERT_DOWNLOADING_10_10_10_2;
-            }
-            else {
-                *revert = REVERT_DOWNLOADING_2_10_10_10;
-            }
-        }
-        break;
-
-    case PICT_r5g6b5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
-
-        break;
-
-    case PICT_b5g6r5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
-        need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;;
-        break;
-
-    case PICT_x1b5g5r5:
-        *no_alpha = 1;
-    case PICT_a1b5g5r5:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
-        if (IS_LITTLE_ENDIAN) {
-            *revert =
-                is_upload ? REVERT_UPLOADING_1_5_5_5 :
-                REVERT_DOWNLOADING_1_5_5_5;
-        }
-        else
-            *revert = REVERT_NONE;
-        break;
-
-    case PICT_x1r5g5b5:
-        *no_alpha = 1;
-    case PICT_a1r5g5b5:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
-        if (IS_LITTLE_ENDIAN) {
-            *revert =
-                is_upload ? REVERT_UPLOADING_1_5_5_5 :
-                REVERT_DOWNLOADING_1_5_5_5;
-        }
-        else
-            *revert = REVERT_NONE;
-        need_swap_rb = 1;
-        break;
-
-    case PICT_a1:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
-        break;
-
-    case PICT_a8:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        *revert = REVERT_NONE;
-        break;
-
-    case PICT_x4r4g4b4:
-        *no_alpha = 1;
-    case PICT_a4r4g4b4:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
-        need_swap_rb = 1;
-        break;
-
-    case PICT_x4b4g4r4:
-        *no_alpha = 1;
-    case PICT_a4b4g4r4:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
-        break;
-
-    default:
-        LogMessageVerb(X_INFO, 0,
-                       "fail to get matched format for %x \n", format);
-        return -1;
-    }
-
-    if (need_swap_rb)
-        *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING;
-    else
-        *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
-    return 0;
-}
-
-#endif
-
 inline static int
 cache_format(GLenum format)
 {
@@ -1209,29 +929,6 @@ cache_format(GLenum format)
     }
 }
 
-static inline int
-glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
-                                       GLenum * format,
-                                       GLenum * type,
-                                       int *no_alpha,
-                                       int *revert, int *swap_rb, int is_upload)
-{
-    glamor_pixmap_private *pixmap_priv;
-    PictFormatShort pict_format;
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
-        pict_format = pixmap_priv->base.picture->format;
-    else
-        pict_format = format_for_depth(pixmap->drawable.depth);
-
-    return glamor_get_tex_format_type_from_pictformat(pict_format,
-                                                      format, type,
-                                                      no_alpha,
-                                                      revert,
-                                                      swap_rb, is_upload);
-}
-
 /* borrowed from uxa */
 static inline Bool
 glamor_get_rgba_from_pixel(CARD32 pixel,
commit 0e4f3414189b1820443b35248e4c9e03f0c2e34e
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 02:04:11 2013 -0800

    glamor: Unifdef the cache format indices.
    
    We only ask for GL_RGB on desktop GL as far as I can see, but now if
    GLES2 did happen to ask for GL_RGB it would return a cache index
    instead of -1.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index a6cdf64..81b46b6 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -197,11 +197,7 @@ struct glamor_saved_procs {
     SetWindowPixmapProcPtr set_window_pixmap;
 };
 
-#ifdef GLAMOR_GLES2
 #define CACHE_FORMAT_COUNT 3
-#else
-#define CACHE_FORMAT_COUNT 2
-#endif
 
 #define CACHE_BUCKET_WCOUNT 4
 #define CACHE_BUCKET_HCOUNT 4
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index d277468..3de6133 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1020,20 +1020,6 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
     return 0;
 }
 
-/* Currently, we use RGBA to represent all formats. */
-inline static int
-cache_format(GLenum format)
-{
-    switch (format) {
-    case GL_ALPHA:
-        return 1;
-    case GL_RGBA:
-        return 0;
-    default:
-        return -1;
-    }
-}
-
 #else
 #define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
 
@@ -1206,6 +1192,8 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
     return 0;
 }
 
+#endif
+
 inline static int
 cache_format(GLenum format)
 {
@@ -1221,8 +1209,6 @@ cache_format(GLenum format)
     }
 }
 
-#endif
-
 static inline int
 glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
                                        GLenum * format,
commit d63283860a7c04a12838dead0dfd6d04fb73a093
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 01:23:15 2013 -0800

    glamor: Pass pixmaps around to unifdef glamor_iformat_for_depth().
    
    v2: Just pass in the PicturePtr to glamor_pict_format_is_compatible()
        (suggestion by keithp)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index baee4dd..7d8228c 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -95,7 +95,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
         glamor_destroy_fbo(fbo);
     }
 
-    gl_iformat_for_depth(pixmap->drawable.depth, &format);
+    format = gl_iformat_for_pixmap(pixmap);
     fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width,
                                      pixmap->drawable.height, format, tex, 0);
 
@@ -162,7 +162,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
     pixmap_priv->base.pixmap = pixmap;
     pixmap_priv->base.glamor_priv = glamor_priv;
 
-    gl_iformat_for_depth(depth, &format);
+    format = gl_iformat_for_pixmap(pixmap);
 
     pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3;
     screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL);
diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c
index f51a7e4..8bbe2e9 100644
--- a/glamor/glamor_picture.c
+++ b/glamor/glamor_picture.c
@@ -93,8 +93,7 @@ glamor_create_picture(PicturePtr picture)
              * we have to mark this pixmap as a separated texture, and don't
              * fallback to DDX layer. */
             if (pixmap_priv->type == GLAMOR_TEXTURE_DRM
-                && !glamor_pict_format_is_compatible(picture->format,
-                                                     pixmap->drawable.depth))
+                && !glamor_pict_format_is_compatible(picture))
                 glamor_set_pixmap_type(pixmap, GLAMOR_SEPARATE_TEXTURE);
         }
     }
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 5442c90..30aeebe 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -403,7 +403,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
     if (*tex == 0) {
         glGenTextures(1, tex);
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-            gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
+            iformat = gl_iformat_for_pixmap(pixmap);
         else
             iformat = format;
         non_sub = 1;
@@ -603,7 +603,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
         return 0;
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
+        iformat = gl_iformat_for_pixmap(pixmap);
     else
         iformat = format;
 
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index eafd2bc..d277468 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -869,19 +869,17 @@ format_for_depth(int depth)
     }
 }
 
-static inline void
-gl_iformat_for_depth(int depth, GLenum * format)
+static inline GLenum
+gl_iformat_for_pixmap(PixmapPtr pixmap)
 {
-    switch (depth) {
-#ifndef GLAMOR_GLES2
-    case 1:
-    case 8:
-        *format = GL_ALPHA;
-        break;
-#endif
-    default:
-        *format = GL_RGBA;
-        break;
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(pixmap->drawable.pScreen);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
+        (pixmap->drawable.depth == 1 || pixmap->drawable.depth == 8)) {
+        return GL_ALPHA;
+    } else {
+        return GL_RGBA;
     }
 }
 
@@ -1319,16 +1317,18 @@ glamor_get_rgba_from_pixel(CARD32 pixel,
 }
 
 inline static Bool
-glamor_pict_format_is_compatible(PictFormatShort pict_format, int depth)
+glamor_pict_format_is_compatible(PicturePtr picture)
 {
     GLenum iformat;
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
 
-    gl_iformat_for_depth(depth, &iformat);
+    iformat = gl_iformat_for_pixmap(pixmap);
     switch (iformat) {
     case GL_RGBA:
-        return (pict_format == PICT_a8r8g8b8 || pict_format == PICT_x8r8g8b8);
+        return (picture->format == PICT_a8r8g8b8 ||
+                picture->format == PICT_x8r8g8b8);
     case GL_ALPHA:
-        return (pict_format == PICT_a8);
+        return (picture->format == PICT_a8);
     default:
         return FALSE;
     }
commit f3f4fc7a65589a200a086ea7b1527f91941bc19b
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 01:17:10 2013 -0800

    glamor: Add a screen argument to drop an ifdef from glamor_set_alu().
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 8cc7cad..d6bcacd 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -338,6 +338,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
                     Bool upsidedown, Pixel bitplane,
                     void *closure, Bool fallback)
 {
+    ScreenPtr screen = dst->pScreen;
     PixmapPtr dst_pixmap, src_pixmap;
     glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
     glamor_screen_private *glamor_priv;
@@ -354,7 +355,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
     src_pixmap = glamor_get_drawable_pixmap(src);
     src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
 
-    glamor_priv = glamor_get_screen_private(dst->pScreen);
+    glamor_priv = glamor_get_screen_private(screen);
 
     DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
            box[0].x1, box[0].y1,
@@ -368,7 +369,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
         if (!glamor_set_planemask(dst_pixmap, gc->planemask))
             goto fall_back;
         glamor_get_context(glamor_priv);
-        if (!glamor_set_alu(gc->alu)) {
+        if (!glamor_set_alu(screen, gc->alu)) {
             glamor_put_context(glamor_priv);
             goto fail;
         }
@@ -546,7 +547,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
 
  fail:
     glamor_get_context(glamor_priv);
-    glamor_set_alu(GXcopy);
+    glamor_set_alu(screen, GXcopy);
     glamor_put_context(glamor_priv);
 
     if (ok)
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index d1c16ad..dda55ea 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -330,7 +330,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
     }
 
     glamor_get_context(glamor_priv);
-    if (!glamor_set_alu(alu)) {
+    if (!glamor_set_alu(screen, alu)) {
         if (alu == GXclear)
             fg_pixel = 0;
         else {
@@ -345,7 +345,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
     box.y2 = y + height;
     glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
 
-    glamor_set_alu(GXcopy);
+    glamor_set_alu(screen, GXcopy);
     glamor_put_context(glamor_priv);
 
     return TRUE;
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 41d5f5a..5442c90 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -115,9 +115,17 @@ glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask)
 }
 
 Bool
-glamor_set_alu(unsigned char alu)
+glamor_set_alu(ScreenPtr screen, unsigned char alu)
 {
-#ifndef GLAMOR_GLES2
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
+        if (alu != GXcopy)
+            return FALSE;
+        else
+            return TRUE;
+    }
+
     if (alu == GXcopy) {
         glDisable(GL_COLOR_LOGIC_OP);
         return TRUE;
@@ -173,10 +181,7 @@ glamor_set_alu(unsigned char alu)
         glamor_fallback("unsupported alu %x\n", alu);
         return FALSE;
     }
-#else
-    if (alu != GXcopy)
-        return FALSE;
-#endif
+
     return TRUE;
 }
 
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 53af353..a6cdf64 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -599,7 +599,7 @@ glamor_pixmap_fbo *glamor_es2_pixmap_read_prepare(PixmapPtr source, int x,
                                                   int no_alpha, int revert,
                                                   int swap_rb);
 
-Bool glamor_set_alu(unsigned char alu);
+Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
 Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask);
 RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index 9abb95d..7288af3 100644
--- a/glamor/glamor_tile.c
+++ b/glamor/glamor_tile.c
@@ -196,7 +196,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     }
 
     glamor_get_context(glamor_priv);
-    if (!glamor_set_alu(alu)) {
+    if (!glamor_set_alu(screen, alu)) {
         glamor_fallback("unsupported alu %x\n", alu);
         glamor_put_context(glamor_priv);
         goto fail;
@@ -291,7 +291,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     else
         _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
 
-    glamor_set_alu(GXcopy);
+    glamor_set_alu(screen, GXcopy);
     glamor_put_context(glamor_priv);
     return TRUE;
  fail:
commit 9553020b7184ed7a7ef3f02d60556d519ea3e769
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 25 11:39:13 2013 -0800

    glamor: Drop a bunch of GLES2 ifdefs.
    
    Now that we're using epoxy, we can write code using both desktop and
    ES symbols and decide what to use at runtime.
    
    v2: Fix a spelling mistake (latter), since the lines were moved
        anyway (noticed by Rémi Cardona).  Fix condition invert in
        glamor_set_composite_texture (caught by Michel Dänzer).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com> (v1)
    Reviewed-by: Adam Jackson <ajax at redhat.com> (v1)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 4c962ac..baee4dd 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -301,26 +301,29 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         goto fail;;
     }
 
+    if (epoxy_is_desktop_gl())
+        glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP;
+    else
+        glamor_priv->gl_flavor = GLAMOR_GL_ES2;
+
     gl_version = glamor_gl_get_version();
 
-#ifndef GLAMOR_GLES2
-    if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) {
-        ErrorF("Require OpenGL version 1.3 or latter.\n");
-        goto fail;
-    }
-#else
-    if (gl_version < GLAMOR_GL_VERSION_ENCODE(2, 0)) {
-        ErrorF("Require Open GLES2.0 or latter.\n");
-        goto fail;
-    }
-#endif
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        if (gl_version < GLAMOR_GL_VERSION_ENCODE(1, 3)) {
+            ErrorF("Require OpenGL version 1.3 or later.\n");
+            goto fail;
+        }
+    } else {
+        if (gl_version < GLAMOR_GL_VERSION_ENCODE(2, 0)) {
+            ErrorF("Require Open GLES2.0 or later.\n");
+            goto fail;
+        }
 
-#ifdef GLAMOR_GLES2
-    if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) {
-        ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
-        goto fail;
+        if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) {
+            ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
+            goto fail;
+        }
     }
-#endif
 
     glamor_priv->has_pack_invert =
         glamor_gl_has_extension("GL_MESA_pack_invert");
@@ -333,11 +336,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 
     glamor_set_debug_level(&glamor_debug_level);
 
-#ifdef GLAMOR_GLES2
-    glamor_priv->gl_flavor = GLAMOR_GL_ES2;
-#else
-    glamor_priv->gl_flavor = GLAMOR_GL_DESKTOP;
-#endif
     /* If we are using egl screen, call egl screen init to
      * register correct close screen function. */
     if (flags & GLAMOR_USE_EGL_SCREEN) {
diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 498a06e..8cc7cad 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -31,7 +31,6 @@
  *
  * GC CopyArea implementation
  */
-#ifndef GLAMOR_GLES2
 static Bool
 glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
                             DrawablePtr dst,
@@ -117,7 +116,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
     glamor_priv->state = BLIT_STATE;
     return TRUE;
 }
-#endif
 
 static Bool
 glamor_copy_n_to_n_textured(DrawablePtr src,
@@ -170,10 +168,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
-#ifndef GLAMOR_GLES2
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-#endif
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+    }
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
@@ -266,15 +264,14 @@ __glamor_copy_n_to_n(DrawablePtr src,
            box[0].x1, box[0].y1,
            box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
            dx, dy, src_pixmap, dst_pixmap);
-#ifndef GLAMOR_GLES2
-    if (!overlaped &&
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
+        !overlaped &&
         (glamor_priv->state != RENDER_STATE
          || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
         && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) {
         ret = TRUE;
         goto done;
     }
-#endif
     glamor_calculate_boxes_bound(&bound, box, nbox);
 
     /*  Overlaped indicate the src and dst are the same pixmap. */
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index c9bd519..d1c16ad 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -240,13 +240,15 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
         }
         if (box_cnt == 1)
             glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
-        else
-#ifndef GLAMOR_GLES2
-            glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
-                                GL_UNSIGNED_SHORT, NULL);
-#else
-            glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT, NULL);
-#endif
+        else {
+            if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+                glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
+                                    GL_UNSIGNED_SHORT, NULL);
+            } else {
+                glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT,
+                               NULL);
+            }
+        }
         nbox -= box_cnt;
         box += box_cnt;
     }
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index ecc4606..093a215 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -535,14 +535,16 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
     repeat_type = picture->repeatType;
     switch (picture->repeatType) {
     case RepeatNone:
-#ifndef GLAMOR_GLES2
-        /* XXX  GLES2 doesn't support GL_CLAMP_TO_BORDER. */
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-#else
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-#endif
+        if (glamor_priv->gl_flavor != GLAMOR_GL_ES2) {
+            /* XXX  GLES2 doesn't support GL_CLAMP_TO_BORDER. */
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+                            GL_CLAMP_TO_BORDER);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+                            GL_CLAMP_TO_BORDER);
+        } else {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        }
         break;
     case RepeatNormal:
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
@@ -807,14 +809,14 @@ glamor_flush_composite_rects(ScreenPtr screen)
     if (!glamor_priv->render_nr_verts)
         return;
 
-#ifndef GLAMOR_GLES2
-    glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts,
-                        (glamor_priv->render_nr_verts * 3) / 2,
-                        GL_UNSIGNED_SHORT, NULL);
-#else
-    glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
-                   GL_UNSIGNED_SHORT, NULL);
-#endif
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts,
+                            (glamor_priv->render_nr_verts * 3) / 2,
+                            GL_UNSIGNED_SHORT, NULL);
+    } else {
+        glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
+                       GL_UNSIGNED_SHORT, NULL);
+    }
     glamor_put_context(glamor_priv);
 }
 
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index e64c19d..7bc925a 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -1554,16 +1554,16 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
                          glamor_priv->vb, GL_DYNAMIC_DRAW);
         }
 
-#ifndef GLAMOR_GLES2
-        glDrawRangeElements(GL_TRIANGLES, 0,
-                            glamor_priv->render_nr_verts,
-                            (glamor_priv->render_nr_verts * 3) / 2,
-                            GL_UNSIGNED_SHORT, NULL);
-#else
-        glDrawElements(GL_TRIANGLES,
-                       (glamor_priv->render_nr_verts * 3) / 2,
-                       GL_UNSIGNED_SHORT, NULL);
-#endif
+        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+            glDrawRangeElements(GL_TRIANGLES, 0,
+                                glamor_priv->render_nr_verts,
+                                (glamor_priv->render_nr_verts * 3) / 2,
+                                GL_UNSIGNED_SHORT, NULL);
+        } else {
+            glDrawElements(GL_TRIANGLES,
+                           (glamor_priv->render_nr_verts * 3) / 2,
+                           GL_UNSIGNED_SHORT, NULL);
+        }
     }
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
commit c3c8a5f36034b6a2ce48d1d42e3de5af36406c38
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 25 11:36:35 2013 -0800

    glamor: yInverted is a boolean value, so use the Bool type.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 5947d7f..4c962ac 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -280,10 +280,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         return FALSE;
 
     if (flags & GLAMOR_INVERTED_Y_AXIS) {
-        glamor_priv->yInverted = 1;
+        glamor_priv->yInverted = TRUE;
     }
     else
-        glamor_priv->yInverted = 0;
+        glamor_priv->yInverted = FALSE;
 
     if (!dixRegisterPrivateKey(glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
         LogMessage(X_WARNING,
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index f2bc002..53af353 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -215,7 +215,7 @@ struct glamor_saved_procs {
 #define RENDER_IDEL_MAX 32
 
 typedef struct glamor_screen_private {
-    int yInverted;
+    Bool yInverted;
     unsigned int tick;
     enum glamor_gl_flavor gl_flavor;
     int has_pack_invert;
commit 12cbfeed81d3ae73e10ee8a2b6619fb4f403b8f6
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 23 18:00:46 2013 -0800

    glamor: Drop fixed function transformation matrix setup.
    
    gl_ModelViewProjection and friends aren't used in our shaders, so this
    setup didn't do anything.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 9fe2b2e..41d5f5a 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -69,12 +69,6 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0,
     glamor_get_context(fbo->glamor_priv);
 
     glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
-#ifndef GLAMOR_GLES2
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-#endif
     glViewport(x0, y0, width, height);
 
     glamor_put_context(fbo->glamor_priv);
commit 62965d278c347ff323f2262d767978794e32f841
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 23 17:50:46 2013 -0800

    glamor: Drop useless glEnable/glDisable(GL_TEXTURE_2D) calls.
    
    Those calls are only for enabling texture handling in the fixed
    function pipeline, while everything we do is with shaders.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 7279d34..498a06e 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -171,7 +171,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
 #ifndef GLAMOR_GLES2
-    glEnable(GL_TEXTURE_2D);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 #endif
@@ -208,9 +207,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-#ifndef GLAMOR_GLES2
-    glDisable(GL_TEXTURE_2D);
-#endif
     glUseProgram(0);
     /* The source texture is bound to a fbo, we have to flush it here. */
     glamor_put_context(glamor_priv);
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 4012755..9fe2b2e 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -538,18 +538,12 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-#ifndef GLAMOR_GLES2
-    glEnable(GL_TEXTURE_2D);
-#endif
     glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
     glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
     glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
 
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-#ifndef GLAMOR_GLES2
-    glDisable(GL_TEXTURE_2D);
-#endif
     glUseProgram(0);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c
index 60ccd67..702e89f 100644
--- a/glamor/glamor_putimage.c
+++ b/glamor/glamor_putimage.c
@@ -170,7 +170,6 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
 
     glGenTextures(1, &tex);
     glActiveTexture(GL_TEXTURE0);
-    glEnable(GL_TEXTURE_2D);
     glBindTexture(GL_TEXTURE_2D, tex);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -220,7 +219,6 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
     glamor_set_alu(GXcopy);
     glamor_set_planemask(pixmap, ~0);
     glDeleteTextures(1, &tex);
-    glDisable(GL_TEXTURE_2D);
     glDisableClientState(GL_VERTEX_ARRAY);
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     return;
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 34530f3..ecc4606 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -572,9 +572,6 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         break;
     }
-#ifndef GLAMOR_GLES2
-    glEnable(GL_TEXTURE_2D);
-#endif
 
     /*
      *  GLES2 doesn't support RepeatNone. We need to fix it anyway.
@@ -1409,12 +1406,6 @@ glamor_composite_with_shader(CARD8 op,
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
     glDisable(GL_BLEND);
-#ifndef GLAMOR_GLES2
-    glActiveTexture(GL_TEXTURE0);
-    glDisable(GL_TEXTURE_2D);
-    glActiveTexture(GL_TEXTURE1);
-    glDisable(GL_TEXTURE_2D);
-#endif
     DEBUGF("finish rendering.\n");
     glUseProgram(0);
     glamor_priv->state = RENDER_STATE;
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index 5b58e80..9abb95d 100644
--- a/glamor/glamor_tile.c
+++ b/glamor/glamor_tile.c
@@ -135,9 +135,6 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-#ifndef GLAMOR_GLES2
-    glEnable(GL_TEXTURE_2D);
-#endif
     glamor_set_repeat_normalize_tcoords
         (src_pixmap_priv, RepeatNormal,
          src_xscale, src_yscale,
@@ -158,9 +155,6 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-#ifndef GLAMOR_GLES2
-    glDisable(GL_TEXTURE_2D);
-#endif
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glUseProgram(0);
     glamor_put_context(glamor_priv);
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 6ef0c1d..e64c19d 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -976,12 +976,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
     glDisable(GL_BLEND);
-#ifndef GLAMOR_GLES2
-    glActiveTexture(GL_TEXTURE0);
-    glDisable(GL_TEXTURE_2D);
-    glActiveTexture(GL_TEXTURE1);
-    glDisable(GL_TEXTURE_2D);
-#endif
     glUseProgram(0);
     glamor_put_context(glamor_priv);
 
commit 4afe15d8bfd575c010ed1868697a7922a37ab378
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 18 15:27:52 2013 -0800

    glamor: Put in a pluggable context switcher for GLX versus EGL.
    
    The GLX side just gets the context from the current state.  That's
    also something I want to do for EGL, so that the making a context is
    separate from initializing glamor, but I think I need the modesetting
    driver in the server before I think about hacking on that more.
    
    The previous code was rather incestuous, along with pulling in xf86
    dependencies to our dix code.  The new code just initializes itself
    from the current state.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 17cae97..12a57c4 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -6,6 +6,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS)
 
 libglamor_la_SOURCES = \
 	glamor.c \
+	glamor_context.h \
 	glamor_copyarea.c \
 	glamor_copywindow.c \
 	glamor_core.c \
@@ -13,6 +14,7 @@ libglamor_la_SOURCES = \
 	glamor_fill.c \
 	glamor_fillspans.c \
 	glamor_getspans.c \
+	glamor_glx.c \
 	glamor_glyphs.c \
 	glamor_polyfillrect.c \
 	glamor_polylines.c \
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 410ebd2..5947d7f 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -340,8 +340,12 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 #endif
     /* If we are using egl screen, call egl screen init to
      * register correct close screen function. */
-    if (flags & GLAMOR_USE_EGL_SCREEN)
-        glamor_egl_screen_init(screen);
+    if (flags & GLAMOR_USE_EGL_SCREEN) {
+        glamor_egl_screen_init(screen, &glamor_priv->ctx);
+    } else {
+        if (!glamor_glx_screen_init(&glamor_priv->ctx))
+            goto fail;
+    }
 
     glamor_priv->saved_procs.close_screen = screen->CloseScreen;
     screen->CloseScreen = glamor_close_screen;
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 05f565b..eec6872 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -36,6 +36,8 @@
 #include <fb.h>
 #include <fbpict.h>
 
+struct glamor_context;
+
 /*
  * glamor_pixmap_type : glamor pixmap's type.
  * @MEMORY: pixmap is in memory.
@@ -142,11 +144,6 @@ extern _X_EXPORT void glamor_block_handler(ScreenPtr screen);
 extern _X_EXPORT PixmapPtr glamor_create_pixmap(ScreenPtr screen, int w, int h,
                                                 int depth, unsigned int usage);
 
-extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen);
-
-extern _X_EXPORT void glamor_egl_make_current(ScreenPtr screen);
-extern _X_EXPORT void glamor_egl_restore_context(ScreenPtr screen);
-
 /* @glamor_egl_exchange_buffers: Exchange the underlying buffers(KHR image,fbo).
  *
  * @front: front pixmap.
diff --git a/glamor/glamor_context.h b/glamor/glamor_context.h
new file mode 100644
index 0000000..8781afc
--- /dev/null
+++ b/glamor/glamor_context.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2013 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.
+ */
+
+/**
+ * @file glamor_context.h
+ *
+ * This is the struct of state required for context switching in
+ * glamor.  It has to use types that don't require including either
+ * server headers or Xlib headers, since it will be included by both
+ * the server and the GLX (xlib) code.
+ */
+
+struct glamor_context {
+    /** Either an EGLDisplay or an Xlib Display */
+    void *display;
+
+    /** Either a GLXContext or an EGLContext. */
+    void *ctx;
+
+    /** The EGLSurface we should MakeCurrent to */
+    void *drawable;
+
+    /** The GLXDrawable we should MakeCurrent to */
+    uint32_t drawable_xid;
+
+    /**
+     * Count of how deep in glamor_get_context() we are, to reduce
+     * MakeCurrent calls.
+     */
+    int get_count;
+
+    void (*get_context)(struct glamor_context *glamor_ctx);
+    void (*put_context)(struct glamor_context *glamor_ctx);
+};
+
+Bool glamor_glx_screen_init(struct glamor_context *glamor_ctx);
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 906598a..81e697b 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -49,6 +49,7 @@
 #include <epoxy/egl.h>
 
 #include "glamor.h"
+#include "glamor_priv.h"
 
 static const char glamor_name[] = "glamor";
 
@@ -87,6 +88,7 @@ struct glamor_egl_screen_private {
 
 int xf86GlamorEGLPrivateIndex = -1;
 
+
 static struct glamor_egl_screen_private *
 glamor_egl_get_screen_private(ScrnInfoPtr scrn)
 {
@@ -94,38 +96,30 @@ glamor_egl_get_screen_private(ScrnInfoPtr scrn)
         scrn->privates[xf86GlamorEGLPrivateIndex].ptr;
 }
 
-_X_EXPORT void
-glamor_egl_make_current(ScreenPtr screen)
+static void
+glamor_egl_get_context(struct glamor_context *glamor_ctx)
 {
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    struct glamor_egl_screen_private *glamor_egl =
-        glamor_egl_get_screen_private(scrn);
-
-    if (glamor_egl->gl_context_depth++)
+    if (glamor_ctx->get_count++)
         return;
 
-    if (glamor_egl->context != eglGetCurrentContext()) {
-        eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE,
+    if (glamor_ctx->ctx != eglGetCurrentContext()) {
+        eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
                        EGL_NO_SURFACE, EGL_NO_CONTEXT);
-        if (!eglMakeCurrent(glamor_egl->display,
+        if (!eglMakeCurrent(glamor_ctx->display,
                             EGL_NO_SURFACE, EGL_NO_SURFACE,
-                            glamor_egl->context)) {
+                            glamor_ctx->ctx)) {
             FatalError("Failed to make EGL context current\n");
         }
     }
 }
 
-_X_EXPORT void
-glamor_egl_restore_context(ScreenPtr screen)
+static void
+glamor_egl_put_context(struct glamor_context *glamor_ctx)
 {
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    struct glamor_egl_screen_private *glamor_egl =
-        glamor_egl_get_screen_private(scrn);
-
-    if (--glamor_egl->gl_context_depth)
+    if (--glamor_ctx->get_count)
         return;
 
-    eglMakeCurrent(glamor_egl->display, EGL_NO_SURFACE,
+    eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
 }
 
@@ -284,6 +278,8 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     GLuint texture;
@@ -292,7 +288,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
-    glamor_egl_make_current(screen);
+    glamor_get_context(glamor_priv);
     if (glamor_egl->has_gem) {
         if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) {
             xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -322,7 +318,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
     ret = TRUE;
 
  done:
-    glamor_egl_restore_context(screen);
+    glamor_put_context(glamor_priv);
     return ret;
 }
 
@@ -331,6 +327,8 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     GLuint texture;
@@ -338,7 +336,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
-    glamor_egl_make_current(screen);
+    glamor_get_context(glamor_priv);
 
     image = eglCreateImageKHR(glamor_egl->display,
                               glamor_egl->context,
@@ -354,7 +352,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
     ret = TRUE;
 
  done:
-    glamor_egl_restore_context(screen);
+    glamor_put_context(glamor_priv);
     return ret;
 }
 
@@ -395,6 +393,8 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 {
 #ifdef GLAMOR_HAS_DRI3_SUPPORT
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl;
     EGLImageKHR image;
     struct gbm_bo *bo;
@@ -408,7 +408,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
-    glamor_egl_make_current(screen);
+    glamor_get_context(glamor_priv);
 
     image = dixLookupPrivate(&pixmap->devPrivates,
                              glamor_egl_pixmap_private_key);
@@ -446,7 +446,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     gbm_bo_destroy(bo);
  failure:
-    glamor_egl_restore_context(screen);
+    glamor_put_context(glamor_priv);
     return fd;
 #else
     return -1;
@@ -628,7 +628,7 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl,
 }
 
 void
-glamor_egl_screen_init(ScreenPtr screen)
+glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
     struct glamor_egl_screen_private *glamor_egl =
@@ -636,6 +636,12 @@ glamor_egl_screen_init(ScreenPtr screen)
 
     glamor_egl->saved_close_screen = screen->CloseScreen;
     screen->CloseScreen = glamor_egl_close_screen;
+
+    glamor_ctx->ctx = glamor_egl->context;
+    glamor_ctx->display = glamor_egl->display;
+
+    glamor_ctx->get_context = glamor_egl_get_context;
+    glamor_ctx->put_context = glamor_egl_put_context;
 }
 
 static void
diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c
index 1449d08..4fd9e80 100644
--- a/glamor/glamor_egl_stubs.c
+++ b/glamor/glamor_egl_stubs.c
@@ -29,7 +29,7 @@
 #include "glamor_priv.h"
 
 void
-glamor_egl_screen_init(ScreenPtr screen)
+glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 {
 }
 
@@ -38,16 +38,6 @@ glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap)
 {
 }
 
-void
-glamor_egl_make_current(ScreenPtr screen)
-{
-}
-
-void
-glamor_egl_restore_context(ScreenPtr screen)
-{
-}
-
 int
 glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
                                  PixmapPtr pixmap,
diff --git a/glamor/glamor_glx.c b/glamor/glamor_glx.c
new file mode 100644
index 0000000..311bf75
--- /dev/null
+++ b/glamor/glamor_glx.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright © 2013 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.
+ */
+
+#include <epoxy/glx.h>
+#include "glamor_context.h"
+
+/**
+ * @file glamor_glx.c
+ *
+ * GLX context management for glamor.
+ *
+ * This has to be kept separate from the server sources because of
+ * Xlib's conflicting definition of CARD32 and similar typedefs.
+ */
+
+static void
+glamor_glx_get_context(struct glamor_context *glamor_ctx)
+{
+    GLXContext old_ctx;
+
+    if (glamor_ctx->get_count++)
+        return;
+
+    old_ctx = glXGetCurrentContext();
+    if (old_ctx == glamor_ctx->ctx)
+        return;
+
+    glXMakeCurrent(glamor_ctx->display, glamor_ctx->drawable_xid,
+                   glamor_ctx->ctx);
+}
+
+
+static void
+glamor_glx_put_context(struct glamor_context *glamor_ctx)
+{
+    if (--glamor_ctx->get_count)
+        return;
+
+    /* We actually reset the context, so that indirect GLX's EGL usage
+     * won't get confused by ours.
+     */
+    glXMakeCurrent(glamor_ctx->display, None, NULL);
+}
+
+Bool
+glamor_glx_screen_init(struct glamor_context *glamor_ctx)
+{
+    glamor_ctx->ctx = glXGetCurrentContext();
+    if (!glamor_ctx->ctx)
+        return False;
+
+    glamor_ctx->display = glXGetCurrentDisplay();
+    if (!glamor_ctx->display)
+        return False;
+
+    glamor_ctx->drawable_xid = glXGetCurrentDrawable();
+
+    glamor_ctx->get_context = glamor_glx_get_context;
+    glamor_ctx->put_context = glamor_glx_put_context;
+
+    return True;
+}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 8477091..f2bc002 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -48,6 +48,7 @@
 #endif
 
 #include "glamor_debug.h"
+#include "glamor_context.h"
 
 #include <list.h>
 
@@ -281,6 +282,8 @@ typedef struct glamor_screen_private {
 
     /* xv */
     GLint xv_prog;
+
+    struct glamor_context ctx;
 } glamor_screen_private;
 
 typedef enum glamor_access {
@@ -927,6 +930,9 @@ void glamor_composite_rectangles(CARD8 op,
                                  xRenderColor *color,
                                  int num_rects, xRectangle *rects);
 
+extern _X_EXPORT void glamor_egl_screen_init(ScreenPtr screen,
+                                             struct glamor_context *glamor_ctx);
+
 /* glamor_xv */
 typedef struct {
     uint32_t transform_index;
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index b82517a..eafd2bc 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1817,29 +1817,15 @@ __fls(unsigned long x)
 #endif
 
 static inline void
-glamor_make_current(ScreenPtr screen)
-{
-    glamor_egl_make_current(screen);
-}
-
-static inline void
-glamor_restore_current(ScreenPtr screen)
-{
-    glamor_egl_restore_context(screen);
-}
-
-static inline void
 glamor_get_context(glamor_screen_private * glamor_priv)
 {
-    if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN)
-        glamor_make_current(glamor_priv->screen);
+    glamor_priv->ctx.get_context(&glamor_priv->ctx);
 }
 
 static inline void
 glamor_put_context(glamor_screen_private * glamor_priv)
 {
-    if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN)
-        glamor_restore_current(glamor_priv->screen);
+    glamor_priv->ctx.put_context(&glamor_priv->ctx);
 }
 
 #endif
commit 781c692cf970642865f0e537f4905c43192f9935
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 18 13:10:24 2013 -0800

    glamor: Rename glamor_get/put_dispatch to glamor_get/put_context.
    
    It used to be the thing that returned your dispatch table and happeend
    to set up the context, but now it just sets up the context.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 74ae150..410ebd2 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -219,11 +219,11 @@ glamor_block_handler(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glamor_priv->tick++;
     glFlush();
     glamor_fbo_expire(glamor_priv);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     if (glamor_priv->state == RENDER_STATE
         && glamor_priv->render_idle_cnt++ > RENDER_IDEL_MAX) {
         glamor_priv->state = IDLE_STATE;
@@ -236,9 +236,9 @@ _glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask)
 {
     glamor_screen_private *glamor_priv = data;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glFlush();
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static void
diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 6eb0d98..7279d34 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -71,7 +71,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
     pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off);
     pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->base.fbo->fb);
     glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
     glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
@@ -113,7 +113,7 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
         }
     }
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     glamor_priv->state = BLIT_STATE;
     return TRUE;
 }
@@ -157,7 +157,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
     glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@@ -213,7 +213,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 #endif
     glUseProgram(0);
     /* The source texture is bound to a fbo, we have to flush it here. */
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
     return TRUE;
@@ -374,12 +374,12 @@ _glamor_copy_n_to_n(DrawablePtr src,
     if (gc) {
         if (!glamor_set_planemask(dst_pixmap, gc->planemask))
             goto fall_back;
-        glamor_get_dispatch(glamor_priv);
+        glamor_get_context(glamor_priv);
         if (!glamor_set_alu(gc->alu)) {
-            glamor_put_dispatch(glamor_priv);
+            glamor_put_context(glamor_priv);
             goto fail;
         }
-        glamor_put_dispatch(glamor_priv);
+        glamor_put_context(glamor_priv);
     }
 
     if (!src_pixmap_priv) {
@@ -552,9 +552,9 @@ _glamor_copy_n_to_n(DrawablePtr src,
     }
 
  fail:
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glamor_set_alu(GXcopy);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     if (ok)
         return TRUE;
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index fe49cb3..5883809 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -215,7 +215,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
     char *source;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glamor_priv->finish_access_prog[0] = glCreateProgram();
     glamor_priv->finish_access_prog[1] = glCreateProgram();
 
@@ -274,7 +274,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
     glUniform1i(sampler_uniform_location, 0);
     glUniform1i(glamor_priv->finish_access_swap_rb[1], 0);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -283,10 +283,10 @@ glamor_fini_finish_access_shaders(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glDeleteProgram(glamor_priv->finish_access_prog[0]);
     glDeleteProgram(glamor_priv->finish_access_prog[1]);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -307,11 +307,11 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
     if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
         assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
 
-        glamor_get_dispatch(glamor_priv);
+        glamor_get_context(glamor_priv);
         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
         glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
-        glamor_put_dispatch(glamor_priv);
+        glamor_put_context(glamor_priv);
 
         pixmap_priv->base.fbo->pbo_valid = FALSE;
         pixmap_priv->base.fbo->pbo = 0;
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index bb7af2c..281cf83 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -129,7 +129,7 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv,
 void
 glamor_purge_fbo(glamor_pixmap_fbo *fbo)
 {
-    glamor_get_dispatch(fbo->glamor_priv);
+    glamor_get_context(fbo->glamor_priv);
 
     if (fbo->fb)
         glDeleteFramebuffers(1, &fbo->fb);
@@ -137,7 +137,7 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo)
         glDeleteTextures(1, &fbo->tex);
     if (fbo->pbo)
         glDeleteBuffers(1, &fbo->pbo);
-    glamor_put_dispatch(fbo->glamor_priv);
+    glamor_put_context(fbo->glamor_priv);
 
     free(fbo);
 }
@@ -180,7 +180,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
 {
     int status;
 
-    glamor_get_dispatch(fbo->glamor_priv);
+    glamor_get_context(fbo->glamor_priv);
 
     if (fbo->fb == 0)
         glGenFramebuffers(1, &fbo->fb);
@@ -219,7 +219,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
         FatalError("destination is framebuffer incomplete: %s [%x]\n",
                    str, status);
     }
-    glamor_put_dispatch(fbo->glamor_priv);
+    glamor_put_context(fbo->glamor_priv);
 }
 
 glamor_pixmap_fbo *
@@ -241,9 +241,9 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
     fbo->glamor_priv = glamor_priv;
 
     if (flag == GLAMOR_CREATE_PIXMAP_MAP) {
-        glamor_get_dispatch(glamor_priv);
+        glamor_get_context(glamor_priv);
         glGenBuffers(1, &fbo->pbo);
-        glamor_put_dispatch(glamor_priv);
+        glamor_put_context(glamor_priv);
         goto done;
     }
 
@@ -341,14 +341,14 @@ _glamor_create_tex(glamor_screen_private *glamor_priv,
                                                        w, h);
     }
     if (!tex) {
-        glamor_get_dispatch(glamor_priv);
+        glamor_get_context(glamor_priv);
         glGenTextures(1, &tex);
         glBindTexture(GL_TEXTURE_2D, tex);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
                      format, GL_UNSIGNED_BYTE, NULL);
-        glamor_put_dispatch(glamor_priv);
+        glamor_put_context(glamor_priv);
     }
     return tex;
 }
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index e98fc5b..c9bd519 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -153,7 +153,7 @@ glamor_init_solid_shader(ScreenPtr screen)
     GLint fs_prog, vs_prog;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glamor_priv->solid_prog = glCreateProgram();
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs);
     fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs);
@@ -166,7 +166,7 @@ glamor_init_solid_shader(ScreenPtr screen)
 
     glamor_priv->solid_color_uniform_location =
         glGetUniformLocation(glamor_priv->solid_prog, "color");
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -175,9 +175,9 @@ glamor_fini_solid_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glDeleteProgram(glamor_priv->solid_prog);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -193,7 +193,7 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glUseProgram(glamor_priv->solid_prog);
 
     glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
@@ -256,7 +256,7 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
 }
@@ -327,13 +327,13 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
         return FALSE;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     if (!glamor_set_alu(alu)) {
         if (alu == GXclear)
             fg_pixel = 0;
         else {
             glamor_fallback("unsupported alu %x\n", alu);
-            glamor_put_dispatch(glamor_priv);
+            glamor_put_context(glamor_priv);
             return FALSE;
         }
     }
@@ -344,7 +344,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
     glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
 
     glamor_set_alu(GXcopy);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     return TRUE;
 }
diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index c118f34..caafa43 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -1278,9 +1278,9 @@ glamor_buffer_glyph(glamor_screen_private *glamor_priv,
                  * thus we have to composite from the cache picture
                  * to the cache picture, we need a flush here to make
                  * sure latter we get the corret glyphs data.*/
-                glamor_get_dispatch(glamor_priv);
+                glamor_get_context(glamor_priv);
                 glFlush();
-                glamor_put_dispatch(glamor_priv);
+                glamor_put_context(glamor_priv);
             }
         }
         else {
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 08df996..4ea441e 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -176,7 +176,7 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count,
         "}\n";
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     if (use_array) {
         XNFasprintf(&gradient_fs,
@@ -353,7 +353,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
         return;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) {
         glDeleteShader(glamor_priv->radial_gradient_shaders
@@ -422,7 +422,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
         radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] =
         fs_getcolor_prog;
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -586,7 +586,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
         return;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) {
         glDeleteShader(glamor_priv->linear_gradient_shaders
                        [SHADER_GRADIENT_VS_PROG][2]);
@@ -652,7 +652,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
         linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][index] =
         fs_getcolor_prog;
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -695,7 +695,7 @@ glamor_fini_gradient_shader(ScreenPtr screen)
     int i = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     for (i = 0; i < 3; i++) {
         /* Linear Gradient */
@@ -737,7 +737,7 @@ glamor_fini_gradient_shader(ScreenPtr screen)
                             [SHADER_GRADIENT_RADIAL][i]);
     }
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -868,7 +868,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
            tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3],
            tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, 0, vertices);
@@ -878,7 +878,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     return 1;
 }
@@ -1021,7 +1021,7 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     GLint r2_uniform_location = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     /* Create a pixmap with VBO. */
     pixmap = glamor_create_pixmap(screen,
@@ -1258,7 +1258,7 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glUseProgram(0);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return dst_picture;
 
  GRADIENT_FAIL:
@@ -1279,7 +1279,7 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return NULL;
 }
 
@@ -1343,7 +1343,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     GLint pt_distance_uniform_location = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     /* Create a pixmap with VBO. */
     pixmap = glamor_create_pixmap(screen,
@@ -1611,7 +1611,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glUseProgram(0);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return dst_picture;
 
  GRADIENT_FAIL:
@@ -1632,7 +1632,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return NULL;
 }
 
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 7f152fc..4012755 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -66,7 +66,7 @@ void
 glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0,
                                   int width, int height)
 {
-    glamor_get_dispatch(fbo->glamor_priv);
+    glamor_get_context(fbo->glamor_priv);
 
     glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
 #ifndef GLAMOR_GLES2
@@ -77,7 +77,7 @@ glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0,
 #endif
     glViewport(x0, y0, width, height);
 
-    glamor_put_dispatch(fbo->glamor_priv);
+    glamor_put_context(fbo->glamor_priv);
 }
 
 void
@@ -400,7 +400,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
     int non_sub = 0;
     unsigned int iformat = 0;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     if (*tex == 0) {
         glGenTextures(1, tex);
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
@@ -425,7 +425,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
 
     if (bits == NULL)
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -522,7 +522,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
                                  x + w, y + h,
                                  glamor_priv->yInverted, vertices);
     /* Slow path, we need to flip y or wire alpha to 1. */
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, 2 * sizeof(float), vertices);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
@@ -556,7 +556,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
     glDeleteTextures(1, &tex);
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     if (need_free_bits)
         free(bits);
@@ -838,7 +838,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
     if (temp_fbo == NULL)
         return NULL;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     temp_xscale = 1.0 / w;
     temp_yscale = 1.0 / h;
 
@@ -876,7 +876,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return temp_fbo;
 }
 
@@ -956,7 +956,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         fbo_y_off = 0;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
     if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
@@ -987,7 +987,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         unsigned int temp_pbo;
         int yy;
 
-        glamor_get_dispatch(glamor_priv);
+        glamor_get_context(glamor_priv);
         glGenBuffers(1, &temp_pbo);
         glBindBuffer(GL_PIXEL_PACK_BUFFER, temp_pbo);
         glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, GL_STREAM_READ);
@@ -1002,7 +1002,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
     }
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     if (need_post_conversion) {
         /* As OpenGL desktop version never enters here.
@@ -1176,10 +1176,10 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
         data = malloc(stride * pixmap->drawable.height);
     }
     else {
-        glamor_get_dispatch(glamor_priv);
+        glamor_get_context(glamor_priv);
         if (pixmap_priv->base.fbo->pbo == 0)
             glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
-        glamor_put_dispatch(glamor_priv);
+        glamor_put_context(glamor_priv);
         pbo = pixmap_priv->base.fbo->pbo;
     }
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 760af83..34530f3 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -316,7 +316,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
     GLint source_sampler_uniform_location, mask_sampler_uniform_location;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     vs = glamor_create_composite_vs(key);
     if (vs == 0)
         goto out;
@@ -365,7 +365,7 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
     }
 
  out:
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static glamor_composite_shader *
@@ -407,7 +407,7 @@ glamor_init_composite_shaders(ScreenPtr screen)
     int eb_size;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glGenBuffers(1, &glamor_priv->vbo);
     glGenBuffers(1, &glamor_priv->ebo);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
@@ -448,7 +448,7 @@ glamor_init_composite_shaders(ScreenPtr screen)
         glamor_priv->vb = (char *) vb;
     }
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -459,7 +459,7 @@ glamor_fini_composite_shaders(ScreenPtr screen)
     int i, j, k;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glDeleteBuffers(1, &glamor_priv->vbo);
     glDeleteBuffers(1, &glamor_priv->ebo);
 
@@ -473,7 +473,7 @@ glamor_fini_composite_shaders(ScreenPtr screen)
     if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb)
         free(glamor_priv->vb);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -529,7 +529,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
     float wh[4];
     int repeat_type;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glActiveTexture(GL_TEXTURE0 + unit);
     glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
     repeat_type = picture->repeatType;
@@ -598,7 +598,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
             repeat_type -= RepeatFix;
     }
     glUniform1i(repeat_location, repeat_type);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -717,7 +717,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 
     vert_size = n_verts * glamor_priv->vb_stride;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
@@ -764,7 +764,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
                                          4 : 2) * sizeof(float)));
         glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
     }
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -797,7 +797,7 @@ glamor_flush_composite_rects(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
         glUnmapBuffer(GL_ARRAY_BUFFER);
     else {
@@ -818,7 +818,7 @@ glamor_flush_composite_rects(ScreenPtr screen)
     glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
                    GL_UNSIGNED_SHORT, NULL);
 #endif
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 int pict_format_combine_tab[][3] = {
@@ -1194,7 +1194,7 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
 
     glamor_priv = dest_priv->base.glamor_priv;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glUseProgram(shader->prog);
 
     if (key->source == SHADER_SOURCE_SOLID) {
@@ -1229,7 +1229,7 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
         glBlendFunc(op_info->source_blend, op_info->dest_blend);
     }
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -1286,7 +1286,7 @@ glamor_composite_with_shader(CARD8 op,
     glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv);
     glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID;
     glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
@@ -1421,7 +1421,7 @@ glamor_composite_with_shader(CARD8 op,
     glamor_priv->render_idle_cnt = 0;
     if (saved_source_format)
         source->format = saved_source_format;
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     ret = TRUE;
     return ret;
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index 8ceb549..5b58e80 100644
--- a/glamor/glamor_tile.c
+++ b/glamor/glamor_tile.c
@@ -62,7 +62,7 @@ glamor_init_tile_shader(ScreenPtr screen)
     GLint sampler_uniform_location;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glamor_priv->tile_prog = glCreateProgram();
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, tile_vs);
     fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs);
@@ -83,7 +83,7 @@ glamor_init_tile_shader(ScreenPtr screen)
     glamor_priv->tile_wh =
         glGetUniformLocation(glamor_priv->tile_prog, "wh");
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -92,9 +92,9 @@ glamor_fini_tile_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glDeleteProgram(glamor_priv->tile_prog);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -124,7 +124,7 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
     pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
     pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glUseProgram(glamor_priv->tile_prog);
 
     glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
@@ -163,7 +163,7 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
 #endif
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
@@ -201,10 +201,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
         goto fail;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     if (!glamor_set_alu(alu)) {
         glamor_fallback("unsupported alu %x\n", alu);
-        glamor_put_dispatch(glamor_priv);
+        glamor_put_context(glamor_priv);
         goto fail;
     }
 
@@ -298,7 +298,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
         _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
 
     glamor_set_alu(GXcopy);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return TRUE;
  fail:
     return FALSE;
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index b398213..6ef0c1d 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -205,7 +205,7 @@ glamor_flush_composite_triangles(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
         glUnmapBuffer(GL_ARRAY_BUFFER);
     else {
@@ -219,7 +219,7 @@ glamor_flush_composite_triangles(ScreenPtr screen)
         return;
 
     glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -602,7 +602,7 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
 
     vert_size = n_verts * glamor_priv->vb_stride;
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -669,7 +669,7 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
                                               stride * sizeof(float)));
     glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -811,7 +811,7 @@ _glamor_trapezoids_with_shader(CARD8 op,
         goto TRAPEZOID_OUT;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     box = REGION_RECTS(&region);
     nbox = REGION_NUM_RECTS(&region);
@@ -983,7 +983,7 @@ _glamor_trapezoids_with_shader(CARD8 op,
     glDisable(GL_TEXTURE_2D);
 #endif
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 
  TRAPEZOID_OUT:
     if (box) {
@@ -1336,7 +1336,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
         "}\n";
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glamor_priv->trapezoid_prog = glCreateProgram();
 
@@ -1361,7 +1361,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
 
     glUseProgram(0);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -1370,9 +1370,9 @@ glamor_fini_trapezoid_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glDeleteProgram(glamor_priv->trapezoid_prog);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -1413,7 +1413,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
         return FALSE;
     }
 
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
@@ -1582,7 +1582,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
     glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     return TRUE;
 }
 
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index d427360..b82517a 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1829,14 +1829,14 @@ glamor_restore_current(ScreenPtr screen)
 }
 
 static inline void
-glamor_get_dispatch(glamor_screen_private * glamor_priv)
+glamor_get_context(glamor_screen_private * glamor_priv)
 {
     if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN)
         glamor_make_current(glamor_priv->screen);
 }
 
 static inline void
-glamor_put_dispatch(glamor_screen_private * glamor_priv)
+glamor_put_context(glamor_screen_private * glamor_priv)
 {
     if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN)
         glamor_restore_current(glamor_priv->screen);
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 89787a4..dc39476 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -93,7 +93,7 @@ glamor_init_xv_shader(ScreenPtr screen)
     GLint fs_prog, vs_prog;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glamor_priv->xv_prog = glCreateProgram();
 
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xv_vs);
@@ -107,7 +107,7 @@ glamor_init_xv_shader(ScreenPtr screen)
                          GLAMOR_VERTEX_SOURCE, "v_texcoord0");
     glamor_link_glsl_prog(glamor_priv->xv_prog);
 
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 void
@@ -116,10 +116,10 @@ glamor_fini_xv_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
 
     glDeleteProgram(glamor_priv->xv_prog);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
 }
 
 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
@@ -324,7 +324,7 @@ glamor_display_textured_video(glamor_port_private *port_priv)
                                   &src_yscale[i]);
         }
     }
-    glamor_get_dispatch(glamor_priv);
+    glamor_get_context(glamor_priv);
     glUseProgram(glamor_priv->xv_prog);
 
     uloc = glGetUniformLocation(glamor_priv->xv_prog, "offsetyco");
@@ -413,7 +413,7 @@ glamor_display_textured_video(glamor_port_private *port_priv)
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
     glUseProgram(0);
-    glamor_put_dispatch(glamor_priv);
+    glamor_put_context(glamor_priv);
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
 
commit 0373b3f4f7c7aec633468b37f9236a2734dbcc74
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 18 12:18:20 2013 -0800

    glamor: Convert to using libepoxy.
    
    Libepoxy hides all the GL versus GLES2 dispatch handling for us, with
    higher performance.
    
    v2: Squash in the later patch to drop the later of two repeated
        glamor_get_dispatch()es instead (caught by keithp)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 21a6591..4859dae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2069,7 +2069,7 @@ dnl glamor
 AM_CONDITIONAL([GLAMOR], [test "x$GLAMOR" = xyes])
 if test "x$GLAMOR" = xyes; then
 	AC_DEFINE(GLAMOR, 1, [Build glamor])
-	PKG_CHECK_MODULES([GLAMOR], [egl gl])
+	PKG_CHECK_MODULES([GLAMOR], [epoxy])
 fi
 
 dnl XWin DDX
diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 3fe2530..17cae97 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -10,11 +10,9 @@ libglamor_la_SOURCES = \
 	glamor_copywindow.c \
 	glamor_core.c \
 	glamor_debug.h \
-	glamor_gl_dispatch.h \
 	glamor_fill.c \
 	glamor_fillspans.c \
 	glamor_getspans.c \
-	glamor_glext.h \
 	glamor_glyphs.c \
 	glamor_polyfillrect.c \
 	glamor_polylines.c \
@@ -35,7 +33,6 @@ libglamor_la_SOURCES = \
 	glamor_largepixmap.c\
 	glamor_picture.c\
 	glamor_window.c\
-	glamor_gl_dispatch.c\
 	glamor_fbo.c\
 	glamor_compositerects.c\
 	glamor_xv.c\
diff --git a/glamor/glamor.c b/glamor/glamor.c
index feb110a..74ae150 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -218,11 +218,10 @@ void
 glamor_block_handler(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
     glamor_priv->tick++;
-    dispatch->glFlush();
+    glFlush();
     glamor_fbo_expire(glamor_priv);
     glamor_put_dispatch(glamor_priv);
     if (glamor_priv->state == RENDER_STATE
@@ -236,9 +235,9 @@ static void
 _glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask)
 {
     glamor_screen_private *glamor_priv = data;
-    glamor_gl_dispatch *dispatch = glamor_get_dispatch(glamor_priv);
 
-    dispatch->glFlush();
+    glamor_get_dispatch(glamor_priv);
+    glFlush();
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -316,8 +315,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     }
 #endif
 
-    glamor_gl_dispatch_init(screen, &glamor_priv->_dispatch, gl_version);
-
 #ifdef GLAMOR_GLES2
     if (!glamor_gl_has_extension("GL_EXT_texture_format_BGRA8888")) {
         ErrorF("GL_EXT_texture_format_BGRA8888 required\n");
@@ -329,8 +326,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         glamor_gl_has_extension("GL_MESA_pack_invert");
     glamor_priv->has_fbo_blit =
         glamor_gl_has_extension("GL_EXT_framebuffer_blit");
-    glamor_priv->_dispatch.glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE,
-                                         &glamor_priv->max_fbo_size);
+    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
 #ifdef MAX_FBO_SIZE
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
 #endif
diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 2735ba0..6eb0d98 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -42,7 +42,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
     PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
     glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
     int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
     int fbo_x_off, fbo_y_off;
     int src_fbo_x_off, src_fbo_y_off;
@@ -72,9 +71,8 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
     pixmap_priv_get_fbo_off(dst_pixmap_priv, &fbo_x_off, &fbo_y_off);
     pixmap_priv_get_fbo_off(src_pixmap_priv, &src_fbo_x_off, &src_fbo_y_off);
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT,
-                                src_pixmap_priv->base.fbo->fb);
+    glamor_get_dispatch(glamor_priv);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, src_pixmap_priv->base.fbo->fb);
     glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
     glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
     dst_x_off += fbo_x_off;
@@ -84,23 +82,15 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
 
     for (i = 0; i < nbox; i++) {
         if (glamor_priv->yInverted) {
-            dispatch->glBlitFramebuffer((box[i].x1 + dx +
-                                         src_x_off),
-                                        (box[i].y1 +
-                                         src_y_off),
-                                        (box[i].x2 + dx +
-                                         src_x_off),
-                                        (box[i].y2 +
-                                         src_y_off),
-                                        (box[i].x1 +
-                                         dst_x_off),
-                                        (box[i].y1 +
-                                         dst_y_off),
-                                        (box[i].x2 +
-                                         dst_x_off),
-                                        (box[i].y2 +
-                                         dst_y_off),
-                                        GL_COLOR_BUFFER_BIT, GL_NEAREST);
+            glBlitFramebuffer(box[i].x1 + dx + src_x_off,
+                              box[i].y1 + src_y_off,
+                              box[i].x2 + dx + src_x_off,
+                              box[i].y2 + src_y_off,
+                              box[i].x1 + dst_x_off,
+                              box[i].y1 + dst_y_off,
+                              box[i].x2 + dst_x_off,
+                              box[i].y2 + dst_y_off,
+                              GL_COLOR_BUFFER_BIT, GL_NEAREST);
         }
         else {
             int flip_dst_y1 =
@@ -112,19 +102,15 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
             int flip_src_y2 =
                 src_pixmap->drawable.height - (box[i].y1 + src_y_off);
 
-            dispatch->glBlitFramebuffer(box[i].x1 + dx +
-                                        src_x_off,
-                                        flip_src_y1,
-                                        box[i].x2 + dx +
-                                        src_x_off,
-                                        flip_src_y2,
-                                        box[i].x1 +
-                                        dst_x_off,
-                                        flip_dst_y1,
-                                        box[i].x2 +
-                                        dst_x_off,
-                                        flip_dst_y2,
-                                        GL_COLOR_BUFFER_BIT, GL_NEAREST);
+            glBlitFramebuffer(box[i].x1 + dx + src_x_off,
+                              flip_src_y1,
+                              box[i].x2 + dx + src_x_off,
+                              flip_src_y2,
+                              box[i].x1 + dst_x_off,
+                              flip_dst_y1,
+                              box[i].x2 + dst_x_off,
+                              flip_dst_y2,
+                              GL_COLOR_BUFFER_BIT, GL_NEAREST);
         }
     }
     glamor_put_dispatch(glamor_priv);
@@ -140,7 +126,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 {
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(dst->pScreen);
-    glamor_gl_dispatch *dispatch;
     PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
     PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
     int i;
@@ -172,37 +157,33 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
     glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), vertices);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, 2 * sizeof(float), vertices);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
     dx += src_x_off;
     dy += src_y_off;
 
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
 #ifndef GLAMOR_GLES2
-    dispatch->glEnable(GL_TEXTURE_2D);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+    glEnable(GL_TEXTURE_2D);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 #endif
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
-                                    GL_FLOAT, GL_FALSE,
-                                    2 * sizeof(float), texcoords);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glUseProgram(glamor_priv->finish_access_prog[0]);
-    dispatch->glUniform1i(glamor_priv->finish_access_revert[0], REVERT_NONE);
-    dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0],
-                          SWAP_NONE_UPLOADING);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), texcoords);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glUseProgram(glamor_priv->finish_access_prog[0]);
+    glUniform1i(glamor_priv->finish_access_revert[0], REVERT_NONE);
+    glUniform1i(glamor_priv->finish_access_swap_rb[0], SWAP_NONE_UPLOADING);
 
     for (i = 0; i < nbox; i++) {
 
@@ -222,15 +203,15 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
                                      box[i].x2 + dx,
                                      box[i].y2 + dy,
                                      glamor_priv->yInverted, texcoords);
-        dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 #ifndef GLAMOR_GLES2
-    dispatch->glDisable(GL_TEXTURE_2D);
+    glDisable(GL_TEXTURE_2D);
 #endif
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
     /* The source texture is bound to a fbo, we have to flush it here. */
     glamor_put_dispatch(glamor_priv);
     glamor_priv->state = RENDER_STATE;
@@ -367,7 +348,6 @@ _glamor_copy_n_to_n(DrawablePtr src,
     PixmapPtr dst_pixmap, src_pixmap;
     glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     BoxPtr extent;
     RegionRec region;
     int src_x_off, src_y_off, dst_x_off, dst_y_off;
@@ -394,8 +374,8 @@ _glamor_copy_n_to_n(DrawablePtr src,
     if (gc) {
         if (!glamor_set_planemask(dst_pixmap, gc->planemask))
             goto fall_back;
-        dispatch = glamor_get_dispatch(glamor_priv);
-        if (!glamor_set_alu(dispatch, gc->alu)) {
+        glamor_get_dispatch(glamor_priv);
+        if (!glamor_set_alu(gc->alu)) {
             glamor_put_dispatch(glamor_priv);
             goto fail;
         }
@@ -572,8 +552,8 @@ _glamor_copy_n_to_n(DrawablePtr src,
     }
 
  fail:
-    dispatch = glamor_get_dispatch(glamor_priv);
-    glamor_set_alu(dispatch, GXcopy);
+    glamor_get_dispatch(glamor_priv);
+    glamor_set_alu(GXcopy);
     glamor_put_dispatch(glamor_priv);
 
     if (ok)
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 4eac856..fe49cb3 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -51,24 +51,23 @@ glamor_get_drawable_location(const DrawablePtr drawable)
 }
 
 GLint
-glamor_compile_glsl_prog(glamor_gl_dispatch * dispatch, GLenum type,
-                         const char *source)
+glamor_compile_glsl_prog(GLenum type, const char *source)
 {
     GLint ok;
     GLint prog;
 
-    prog = dispatch->glCreateShader(type);
-    dispatch->glShaderSource(prog, 1, (const GLchar **) &source, NULL);
-    dispatch->glCompileShader(prog);
-    dispatch->glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
+    prog = glCreateShader(type);
+    glShaderSource(prog, 1, (const GLchar **) &source, NULL);
+    glCompileShader(prog);
+    glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
     if (!ok) {
         GLchar *info;
         GLint size;
 
-        dispatch->glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
+        glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
         info = malloc(size);
         if (info) {
-            dispatch->glGetShaderInfoLog(prog, size, NULL, info);
+            glGetShaderInfoLog(prog, size, NULL, info);
             ErrorF("Failed to compile %s: %s\n",
                    type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
             ErrorF("Program source:\n%s", source);
@@ -83,20 +82,20 @@ glamor_compile_glsl_prog(glamor_gl_dispatch * dispatch, GLenum type,
 }
 
 void
-glamor_link_glsl_prog(glamor_gl_dispatch * dispatch, GLint prog)
+glamor_link_glsl_prog(GLint prog)
 {
     GLint ok;
 
-    dispatch->glLinkProgram(prog);
-    dispatch->glGetProgramiv(prog, GL_LINK_STATUS, &ok);
+    glLinkProgram(prog);
+    glGetProgramiv(prog, GL_LINK_STATUS, &ok);
     if (!ok) {
         GLchar *info;
         GLint size;
 
-        dispatch->glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
+        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
         info = malloc(size);
 
-        dispatch->glGetProgramInfoLog(prog, size, NULL, info);
+        glGetProgramInfoLog(prog, size, NULL, info);
         ErrorF("Failed to link: %s\n", info);
         FatalError("GLSL link failure\n");
     }
@@ -143,7 +142,6 @@ void
 glamor_init_finish_access_shaders(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     const char *vs_source =
         "attribute vec4 v_position;\n"
         "attribute vec4 v_texcoord0;\n"
@@ -217,72 +215,65 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
     char *source;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    glamor_priv->finish_access_prog[0] = dispatch->glCreateProgram();
-    glamor_priv->finish_access_prog[1] = dispatch->glCreateProgram();
+    glamor_get_dispatch(glamor_priv);
+    glamor_priv->finish_access_prog[0] = glCreateProgram();
+    glamor_priv->finish_access_prog[1] = glCreateProgram();
 
-    vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source);
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source);
 
     XNFasprintf(&source, "%s%s", common_source, fs_source);
-    fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, source);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source);
     free(source);
 
-    dispatch->glAttachShader(glamor_priv->finish_access_prog[0], vs_prog);
-    dispatch->glAttachShader(glamor_priv->finish_access_prog[0], fs_prog);
+    glAttachShader(glamor_priv->finish_access_prog[0], vs_prog);
+    glAttachShader(glamor_priv->finish_access_prog[0], fs_prog);
 
-    avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_source);
+    avs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source);
 
     XNFasprintf(&source, "%s%s", common_source, set_alpha_source);
-    set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER,
+    set_alpha_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER,
                                               source);
     free(source);
 
-    dispatch->glAttachShader(glamor_priv->finish_access_prog[1], avs_prog);
-    dispatch->glAttachShader(glamor_priv->finish_access_prog[1],
-                             set_alpha_prog);
+    glAttachShader(glamor_priv->finish_access_prog[1], avs_prog);
+    glAttachShader(glamor_priv->finish_access_prog[1], set_alpha_prog);
 
-    dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0],
-                                   GLAMOR_VERTEX_POS, "v_position");
-    dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[0],
-                                   GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[0]);
+    glBindAttribLocation(glamor_priv->finish_access_prog[0],
+                         GLAMOR_VERTEX_POS, "v_position");
+    glBindAttribLocation(glamor_priv->finish_access_prog[0],
+                         GLAMOR_VERTEX_SOURCE, "v_texcoord0");
+    glamor_link_glsl_prog(glamor_priv->finish_access_prog[0]);
 
-    dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1],
-                                   GLAMOR_VERTEX_POS, "v_position");
-    dispatch->glBindAttribLocation(glamor_priv->finish_access_prog[1],
-                                   GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(dispatch, glamor_priv->finish_access_prog[1]);
+    glBindAttribLocation(glamor_priv->finish_access_prog[1],
+                         GLAMOR_VERTEX_POS, "v_position");
+    glBindAttribLocation(glamor_priv->finish_access_prog[1],
+                         GLAMOR_VERTEX_SOURCE, "v_texcoord0");
+    glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]);
 
     glamor_priv->finish_access_revert[0] =
-        dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0],
-                                       "revert");
+        glGetUniformLocation(glamor_priv->finish_access_prog[0], "revert");
 
     glamor_priv->finish_access_swap_rb[0] =
-        dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0],
-                                       "swap_rb");
+        glGetUniformLocation(glamor_priv->finish_access_prog[0], "swap_rb");
     sampler_uniform_location =
-        dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[0],
-                                       "sampler");
-    dispatch->glUseProgram(glamor_priv->finish_access_prog[0]);
-    dispatch->glUniform1i(sampler_uniform_location, 0);
-    dispatch->glUniform1i(glamor_priv->finish_access_revert[0], 0);
-    dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0);
-    dispatch->glUseProgram(0);
+        glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler");
+    glUseProgram(glamor_priv->finish_access_prog[0]);
+    glUniform1i(sampler_uniform_location, 0);
+    glUniform1i(glamor_priv->finish_access_revert[0], 0);
+    glUniform1i(glamor_priv->finish_access_swap_rb[0], 0);
+    glUseProgram(0);
 
     glamor_priv->finish_access_revert[1] =
-        dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1],
-                                       "revert");
+        glGetUniformLocation(glamor_priv->finish_access_prog[1], "revert");
     glamor_priv->finish_access_swap_rb[1] =
-        dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1],
-                                       "swap_rb");
+        glGetUniformLocation(glamor_priv->finish_access_prog[1], "swap_rb");
     sampler_uniform_location =
-        dispatch->glGetUniformLocation(glamor_priv->finish_access_prog[1],
-                                       "sampler");
-    dispatch->glUseProgram(glamor_priv->finish_access_prog[1]);
-    dispatch->glUniform1i(glamor_priv->finish_access_revert[1], 0);
-    dispatch->glUniform1i(sampler_uniform_location, 0);
-    dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1], 0);
-    dispatch->glUseProgram(0);
+        glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler");
+    glUseProgram(glamor_priv->finish_access_prog[1]);
+    glUniform1i(glamor_priv->finish_access_revert[1], 0);
+    glUniform1i(sampler_uniform_location, 0);
+    glUniform1i(glamor_priv->finish_access_swap_rb[1], 0);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -290,12 +281,11 @@ void
 glamor_fini_finish_access_shaders(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glDeleteProgram(glamor_priv->finish_access_prog[0]);
-    dispatch->glDeleteProgram(glamor_priv->finish_access_prog[1]);
+    glamor_get_dispatch(glamor_priv);
+    glDeleteProgram(glamor_priv->finish_access_prog[0]);
+    glDeleteProgram(glamor_priv->finish_access_prog[1]);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -315,14 +305,12 @@ glamor_finish_access(DrawablePtr drawable, glamor_access_t access_mode)
     }
 
     if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
-        glamor_gl_dispatch *dispatch;
-
         assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
 
-        dispatch = glamor_get_dispatch(glamor_priv);
-        dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-        dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-        dispatch->glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
+        glamor_get_dispatch(glamor_priv);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+        glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
         glamor_put_dispatch(glamor_priv);
 
         pixmap_priv->base.fbo->pbo_valid = FALSE;
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 2f97a83..906598a 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -37,8 +37,6 @@
 #include <errno.h>
 #include <xf86.h>
 #include <xf86drm.h>
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
 #define EGL_DISPLAY_NO_X_MESA
 
 #ifdef GLAMOR_HAS_GBM
@@ -46,19 +44,11 @@
 #include <drm_fourcc.h>
 #endif
 
-#if GLAMOR_GLES2
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#else
-#include <GL/gl.h>
-#endif
-
 #define MESA_EGL_NO_X11_HEADERS
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
+#include <epoxy/gl.h>
+#include <epoxy/egl.h>
 
 #include "glamor.h"
-#include "glamor_gl_dispatch.h"
 
 static const char glamor_name[] = "glamor";
 
@@ -91,10 +81,6 @@ struct glamor_egl_screen_private {
     int gl_context_depth;
     int dri3_capable;
 
-    PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr;
-    PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr;
-    PFNGLEGLIMAGETARGETTEXTURE2DOESPROC egl_image_target_texture2d_oes;
-    struct glamor_gl_dispatch *dispatch;
     CloseScreenProcPtr saved_close_screen;
     xf86FreeScreenProc *saved_free_screen;
 };
@@ -164,11 +150,11 @@ _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl,
     attribs[5] = stride;
     if (depth != 32 && depth != 24)
         return EGL_NO_IMAGE_KHR;
-    image = glamor_egl->egl_create_image_khr(glamor_egl->display,
-                                             glamor_egl->context,
-                                             EGL_DRM_BUFFER_MESA,
-                                             (void *) (uintptr_t) name,
-                                             attribs);
+    image = eglCreateImageKHR(glamor_egl->display,
+                              glamor_egl->context,
+                              EGL_DRM_BUFFER_MESA,
+                              (void *) (uintptr_t) name,
+                              attribs);
     if (image == EGL_NO_IMAGE_KHR)
         return EGL_NO_IMAGE_KHR;
 
@@ -192,15 +178,13 @@ glamor_create_texture_from_image(struct glamor_egl_screen_private
                                  *glamor_egl,
                                  EGLImageKHR image, GLuint * texture)
 {
-    glamor_egl->dispatch->glGenTextures(1, texture);
-    glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, *texture);
-    glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D,
-                                          GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glamor_egl->dispatch->glTexParameteri(GL_TEXTURE_2D,
-                                          GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    (glamor_egl->egl_image_target_texture2d_oes) (GL_TEXTURE_2D, image);
-    glamor_egl->dispatch->glBindTexture(GL_TEXTURE_2D, 0);
+    glGenTextures(1, texture);
+    glBindTexture(GL_TEXTURE_2D, *texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
+    glBindTexture(GL_TEXTURE_2D, 0);
     return TRUE;
 }
 
@@ -228,15 +212,15 @@ glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
      * compile with dri3 support enabled */
     native_pixmap = bo;
 
-    image = glamor_egl->egl_create_image_khr(glamor_egl->display,
-                                             EGL_NO_CONTEXT,
-                                             EGL_NATIVE_PIXMAP_KHR,
-                                             native_pixmap, NULL);
+    image = eglCreateImageKHR(glamor_egl->display,
+                              EGL_NO_CONTEXT,
+                              EGL_NATIVE_PIXMAP_KHR,
+                              native_pixmap, NULL);
     gbm_bo_destroy(bo);
     if (image == EGL_NO_IMAGE_KHR)
         return 0;
     glamor_create_texture_from_image(glamor_egl, image, &texture);
-    glamor_egl->egl_destroy_image_khr(glamor_egl->display, image);
+    eglDestroyImageKHR(glamor_egl->display, image);
 
     return texture;
 #else
@@ -356,9 +340,9 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
 
     glamor_egl_make_current(screen);
 
-    image = glamor_egl->egl_create_image_khr(glamor_egl->display,
-                                             glamor_egl->context,
-                                             EGL_NATIVE_PIXMAP_KHR, bo, NULL);
+    image = eglCreateImageKHR(glamor_egl->display,
+                              glamor_egl->context,
+                              EGL_NATIVE_PIXMAP_KHR, bo, NULL);
     if (image == EGL_NO_IMAGE_KHR) {
         glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY);
         goto done;
@@ -430,11 +414,11 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
                              glamor_egl_pixmap_private_key);
 
     if (image == EGL_NO_IMAGE_KHR || image == NULL) {
-        image = glamor_egl->egl_create_image_khr(glamor_egl->display,
-                                                 glamor_egl->context,
-                                                 EGL_GL_TEXTURE_2D_KHR,
-                                                 (EGLClientBuffer) (uintptr_t)
-                                                 tex, attribs);
+        image = eglCreateImageKHR(glamor_egl->display,
+                                  glamor_egl->context,
+                                  EGL_GL_TEXTURE_2D_KHR,
+                                  (EGLClientBuffer) (uintptr_t)
+                                  tex, attribs);
         if (image == EGL_NO_IMAGE_KHR)
             goto failure;
 
@@ -506,10 +490,10 @@ glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
     attribs[3] = height;
     attribs[7] = fd;
     attribs[11] = stride;
-    image = glamor_egl->egl_create_image_khr(glamor_egl->display,
-                                             EGL_NO_CONTEXT,
-                                             EGL_LINUX_DMA_BUF_EXT,
-                                             NULL, attribs);
+    image = eglCreateImageKHR(glamor_egl->display,
+                              EGL_NO_CONTEXT,
+                              EGL_LINUX_DMA_BUF_EXT,
+                              NULL, attribs);
 
     if (image == EGL_NO_IMAGE_KHR)
         return NULL;
@@ -518,7 +502,7 @@ glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
      * usage of the image. Use gbm_bo to bypass the limitations. */
 
     bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_EGL_IMAGE, image, 0);
-    glamor_egl->egl_destroy_image_khr(glamor_egl->display, image);
+    eglDestroyImageKHR(glamor_egl->display, image);
 
     if (!bo)
         return NULL;
@@ -555,7 +539,7 @@ _glamor_egl_destroy_pixmap_image(PixmapPtr pixmap)
          * a texture. we must call glFlush to make sure the
          * operation on that texture has been done.*/
         glamor_block_handler(pixmap->drawable.pScreen);
-        glamor_egl->egl_destroy_image_khr(glamor_egl->display, image);
+        eglDestroyImageKHR(glamor_egl->display, image);
         dixSetPrivate(&pixmap->devPrivates, glamor_egl_pixmap_private_key,
                       NULL);
     }
@@ -605,8 +589,7 @@ glamor_egl_close_screen(ScreenPtr screen)
     glamor_egl = glamor_egl_get_screen_private(scrn);
     screen_pixmap = screen->GetScreenPixmap(screen);
 
-    glamor_egl->egl_destroy_image_khr(glamor_egl->display,
-                                      glamor_egl->front_image);
+    eglDestroyImageKHR(glamor_egl->display,glamor_egl->front_image);
     dixSetPrivate(&screen_pixmap->devPrivates, glamor_egl_pixmap_private_key,
                   NULL);
     glamor_egl->front_image = NULL;
@@ -614,7 +597,7 @@ glamor_egl_close_screen(ScreenPtr screen)
         back_image = dixLookupPrivate(&(*glamor_egl->back_pixmap)->devPrivates,
                                       glamor_egl_pixmap_private_key);
         if (back_image != NULL && back_image != EGL_NO_IMAGE_KHR) {
-            glamor_egl->egl_destroy_image_khr(glamor_egl->display, back_image);
+            eglDestroyImageKHR(glamor_egl->display, back_image);
             dixSetPrivate(&(*glamor_egl->back_pixmap)->devPrivates,
                           glamor_egl_pixmap_private_key, NULL);
         }
@@ -751,21 +734,6 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
         glamor_egl_has_extension(glamor_egl, "EGL_EXT_image_dma_buf_import"))
         glamor_egl->dri3_capable = TRUE;
 #endif
-    glamor_egl->egl_create_image_khr = (PFNEGLCREATEIMAGEKHRPROC)
-        eglGetProcAddress("eglCreateImageKHR");
-
-    glamor_egl->egl_destroy_image_khr = (PFNEGLDESTROYIMAGEKHRPROC)
-        eglGetProcAddress("eglDestroyImageKHR");
-
-    glamor_egl->egl_image_target_texture2d_oes =
-        (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
-        eglGetProcAddress("glEGLImageTargetTexture2DOES");
-
-    if (!glamor_egl->egl_create_image_khr
-        || !glamor_egl->egl_image_target_texture2d_oes) {
-        xf86DrvMsg(scrn->scrnIndex, X_ERROR, "eglGetProcAddress() failed\n");
-        return FALSE;
-    }
 
     glamor_egl->context = eglCreateContext(glamor_egl->display,
                                            NULL, EGL_NO_CONTEXT,
@@ -809,17 +777,3 @@ glamor_egl_init_textured_pixmap(ScreenPtr screen)
         glamor_enable_dri3(screen);
     return TRUE;
 }
-
-Bool
-glamor_gl_dispatch_init(ScreenPtr screen,
-                        struct glamor_gl_dispatch *dispatch, int gl_version)
-{
-    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
-    struct glamor_egl_screen_private *glamor_egl =
-        glamor_egl_get_screen_private(scrn);
-    if (!glamor_gl_dispatch_init_impl
-        (dispatch, gl_version, (get_proc_address_t) eglGetProcAddress))
-        return FALSE;
-    glamor_egl->dispatch = dispatch;
-    return TRUE;
-}
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index d94e530..bb7af2c 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -129,14 +129,14 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv,
 void
 glamor_purge_fbo(glamor_pixmap_fbo *fbo)
 {
-    glamor_gl_dispatch *dispatch = glamor_get_dispatch(fbo->glamor_priv);
+    glamor_get_dispatch(fbo->glamor_priv);
 
     if (fbo->fb)
-        dispatch->glDeleteFramebuffers(1, &fbo->fb);
+        glDeleteFramebuffers(1, &fbo->fb);
     if (fbo->tex)
-        dispatch->glDeleteTextures(1, &fbo->tex);
+        glDeleteTextures(1, &fbo->tex);
     if (fbo->pbo)
-        dispatch->glDeleteBuffers(1, &fbo->pbo);
+        glDeleteBuffers(1, &fbo->pbo);
     glamor_put_dispatch(fbo->glamor_priv);
 
     free(fbo);
@@ -178,19 +178,17 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
 static void
 glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
 {
-    glamor_gl_dispatch *dispatch;
     int status;
 
-    dispatch = glamor_get_dispatch(fbo->glamor_priv);
+    glamor_get_dispatch(fbo->glamor_priv);
 
     if (fbo->fb == 0)
-        dispatch->glGenFramebuffers(1, &fbo->fb);
+        glGenFramebuffers(1, &fbo->fb);
     assert(fbo->tex != 0);
-    dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
-    dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER,
-                                     GL_COLOR_ATTACHMENT0,
-                                     GL_TEXTURE_2D, fbo->tex, 0);
-    status = dispatch->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                           GL_TEXTURE_2D, fbo->tex, 0);
+    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
     if (status != GL_FRAMEBUFFER_COMPLETE) {
         const char *str;
 
@@ -243,10 +241,8 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
     fbo->glamor_priv = glamor_priv;
 
     if (flag == GLAMOR_CREATE_PIXMAP_MAP) {
-        glamor_gl_dispatch *dispatch;
-
-        dispatch = glamor_get_dispatch(glamor_priv);
-        dispatch->glGenBuffers(1, &fbo->pbo);
+        glamor_get_dispatch(glamor_priv);
+        glGenBuffers(1, &fbo->pbo);
         glamor_put_dispatch(glamor_priv);
         goto done;
     }
@@ -334,7 +330,6 @@ static int
 _glamor_create_tex(glamor_screen_private *glamor_priv,
                    int w, int h, GLenum format)
 {
-    glamor_gl_dispatch *dispatch;
     unsigned int tex = 0;
 
     /* With dri3, we want to allocate ARGB8888 pixmaps only.
@@ -346,15 +341,13 @@ _glamor_create_tex(glamor_screen_private *glamor_priv,
                                                        w, h);
     }
     if (!tex) {
-        dispatch = glamor_get_dispatch(glamor_priv);
-        dispatch->glGenTextures(1, &tex);
-        dispatch->glBindTexture(GL_TEXTURE_2D, tex);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
-                                  GL_NEAREST);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
-                                  GL_NEAREST);
-        dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
-                               format, GL_UNSIGNED_BYTE, NULL);
+        glamor_get_dispatch(glamor_priv);
+        glGenTextures(1, &tex);
+        glBindTexture(GL_TEXTURE_2D, tex);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
+                     format, GL_UNSIGNED_BYTE, NULL);
         glamor_put_dispatch(glamor_priv);
     }
     return tex;
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index d59e620..e98fc5b 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -137,7 +137,6 @@ void
 glamor_init_solid_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     const char *solid_vs =
         "attribute vec4 v_position;"
         "void main()\n"
@@ -154,19 +153,19 @@ glamor_init_solid_shader(ScreenPtr screen)
     GLint fs_prog, vs_prog;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    glamor_priv->solid_prog = dispatch->glCreateProgram();
-    vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, solid_vs);
-    fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, solid_fs);
-    dispatch->glAttachShader(glamor_priv->solid_prog, vs_prog);
-    dispatch->glAttachShader(glamor_priv->solid_prog, fs_prog);
+    glamor_get_dispatch(glamor_priv);
+    glamor_priv->solid_prog = glCreateProgram();
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, solid_vs);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, solid_fs);
+    glAttachShader(glamor_priv->solid_prog, vs_prog);
+    glAttachShader(glamor_priv->solid_prog, fs_prog);
 
-    dispatch->glBindAttribLocation(glamor_priv->solid_prog,
-                                   GLAMOR_VERTEX_POS, "v_position");
-    glamor_link_glsl_prog(dispatch, glamor_priv->solid_prog);
+    glBindAttribLocation(glamor_priv->solid_prog,
+                         GLAMOR_VERTEX_POS, "v_position");
+    glamor_link_glsl_prog(glamor_priv->solid_prog);
 
     glamor_priv->solid_color_uniform_location =
-        dispatch->glGetUniformLocation(glamor_priv->solid_prog, "color");
+        glGetUniformLocation(glamor_priv->solid_prog, "color");
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -174,11 +173,10 @@ void
 glamor_fini_solid_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glDeleteProgram(glamor_priv->solid_prog);
+    glamor_get_dispatch(glamor_priv);
+    glDeleteProgram(glamor_priv->solid_prog);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -188,7 +186,6 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     ScreenPtr screen = pixmap->drawable.pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    glamor_gl_dispatch *dispatch;
     GLfloat xscale, yscale;
     float vertices[32];
     float *pvertices = vertices;
@@ -196,10 +193,10 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glUseProgram(glamor_priv->solid_prog);
+    glamor_get_dispatch(glamor_priv);
+    glUseProgram(glamor_priv->solid_prog);
 
-    dispatch->glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
 
     pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
 
@@ -221,11 +218,11 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     }
 
     if (_X_UNLIKELY(nbox > 1))
-        dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), pvertices);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, 2 * sizeof(float), pvertices);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     while (nbox) {
         int box_cnt, i;
@@ -242,16 +239,13 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
             valid_vertices += 4 * 2;
         }
         if (box_cnt == 1)
-            dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
+            glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
         else
 #ifndef GLAMOR_GLES2
-            dispatch->glDrawRangeElements(GL_TRIANGLES,
-                                          0,
-                                          box_cnt * 4,
-                                          box_cnt * 6, GL_UNSIGNED_SHORT, NULL);
+            glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
+                                GL_UNSIGNED_SHORT, NULL);
 #else
-            dispatch->glDrawElements(GL_TRIANGLES,
-                                     box_cnt * 6, GL_UNSIGNED_SHORT, NULL);
+            glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT, NULL);
 #endif
         nbox -= box_cnt;
         box += box_cnt;
@@ -260,8 +254,8 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
     if (pvertices != vertices)
         free(pvertices);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
@@ -321,7 +315,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
     ScreenPtr screen = pixmap->drawable.pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_pixmap_private *pixmap_priv;
-    glamor_gl_dispatch *dispatch;
     BoxRec box;
 
     pixmap_priv = glamor_get_pixmap_private(pixmap);
@@ -334,8 +327,8 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
         return FALSE;
     }
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    if (!glamor_set_alu(dispatch, alu)) {
+    glamor_get_dispatch(glamor_priv);
+    if (!glamor_set_alu(alu)) {
         if (alu == GXclear)
             fg_pixel = 0;
         else {
@@ -350,7 +343,7 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
     box.y2 = y + height;
     glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
 
-    glamor_set_alu(dispatch, GXcopy);
+    glamor_set_alu(GXcopy);
     glamor_put_dispatch(glamor_priv);
 
     return TRUE;
diff --git a/glamor/glamor_gl_dispatch.c b/glamor/glamor_gl_dispatch.c
deleted file mode 100644
index 0bdda9c..0000000
--- a/glamor/glamor_gl_dispatch.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * 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:
- *    Zhigang Gong <zhigang.gong at gmail.com>
- *
- */
-
-#include "glamor_priv.h"
-#include <dlfcn.h>
-
-#define INIT_FUNC(dst,func_name,get)			\
-  dst->func_name = get(#func_name);			\
-  if (dst->func_name == NULL) {				\
-    dst->func_name = (void *)dlsym(NULL, #func_name);	\
-    if (dst->func_name == NULL) {			\
-      ErrorF("Failed to get function %s\n", #func_name);\
-      goto fail;					\
-    }							\
-  }							\
-
-_X_EXPORT Bool
-glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch,
-                             int gl_version,
-                             void *(*get_proc_address) (const char *))
-{
-#ifndef GLAMOR_GLES2
-    INIT_FUNC(dispatch, glMatrixMode, get_proc_address);
-    INIT_FUNC(dispatch, glLoadIdentity, get_proc_address);
-    INIT_FUNC(dispatch, glRasterPos2i, get_proc_address);
-    INIT_FUNC(dispatch, glDrawPixels, get_proc_address);
-    INIT_FUNC(dispatch, glLogicOp, get_proc_address);
-    INIT_FUNC(dispatch, glMapBuffer, get_proc_address);
-    INIT_FUNC(dispatch, glMapBufferRange, get_proc_address);
-    INIT_FUNC(dispatch, glUnmapBuffer, get_proc_address);
-    INIT_FUNC(dispatch, glBlitFramebuffer, get_proc_address);
-    INIT_FUNC(dispatch, glDrawRangeElements, get_proc_address);
-#endif
-    INIT_FUNC(dispatch, glViewport, get_proc_address);
-    INIT_FUNC(dispatch, glDrawArrays, get_proc_address);
-    INIT_FUNC(dispatch, glDrawElements, get_proc_address);
-    INIT_FUNC(dispatch, glReadPixels, get_proc_address);
-    INIT_FUNC(dispatch, glPixelStorei, get_proc_address);
-    INIT_FUNC(dispatch, glTexParameteri, get_proc_address);
-    INIT_FUNC(dispatch, glTexImage2D, get_proc_address);
-    INIT_FUNC(dispatch, glGenTextures, get_proc_address);
-    INIT_FUNC(dispatch, glDeleteTextures, get_proc_address);
-    INIT_FUNC(dispatch, glBindTexture, get_proc_address);
-    INIT_FUNC(dispatch, glTexSubImage2D, get_proc_address);
-    INIT_FUNC(dispatch, glFlush, get_proc_address);
-    INIT_FUNC(dispatch, glFinish, get_proc_address);
-    INIT_FUNC(dispatch, glGetIntegerv, get_proc_address);
-    INIT_FUNC(dispatch, glGetString, get_proc_address);
-    INIT_FUNC(dispatch, glScissor, get_proc_address);
-    INIT_FUNC(dispatch, glEnable, get_proc_address);
-    INIT_FUNC(dispatch, glDisable, get_proc_address);
-    INIT_FUNC(dispatch, glBlendFunc, get_proc_address);
-    INIT_FUNC(dispatch, glActiveTexture, get_proc_address);
-    INIT_FUNC(dispatch, glGenBuffers, get_proc_address);
-    INIT_FUNC(dispatch, glBufferData, get_proc_address);
-    INIT_FUNC(dispatch, glBindBuffer, get_proc_address);
-    INIT_FUNC(dispatch, glDeleteBuffers, get_proc_address);
-    INIT_FUNC(dispatch, glFramebufferTexture2D, get_proc_address);
-    INIT_FUNC(dispatch, glBindFramebuffer, get_proc_address);
-    INIT_FUNC(dispatch, glDeleteFramebuffers, get_proc_address);
-    INIT_FUNC(dispatch, glGenFramebuffers, get_proc_address);
-    INIT_FUNC(dispatch, glCheckFramebufferStatus, get_proc_address);
-    INIT_FUNC(dispatch, glVertexAttribPointer, get_proc_address);
-    INIT_FUNC(dispatch, glDisableVertexAttribArray, get_proc_address);
-    INIT_FUNC(dispatch, glEnableVertexAttribArray, get_proc_address);
-    INIT_FUNC(dispatch, glBindAttribLocation, get_proc_address);
-    INIT_FUNC(dispatch, glLinkProgram, get_proc_address);
-    INIT_FUNC(dispatch, glShaderSource, get_proc_address);
-
-    INIT_FUNC(dispatch, glUseProgram, get_proc_address);
-    INIT_FUNC(dispatch, glUniform1i, get_proc_address);
-    INIT_FUNC(dispatch, glUniform1f, get_proc_address);
-    INIT_FUNC(dispatch, glUniform4f, get_proc_address);
-    INIT_FUNC(dispatch, glUniform4fv, get_proc_address);
-    INIT_FUNC(dispatch, glUniform1fv, get_proc_address);
-    INIT_FUNC(dispatch, glUniform2fv, get_proc_address);
-    INIT_FUNC(dispatch, glUniformMatrix3fv, get_proc_address);
-    INIT_FUNC(dispatch, glCreateProgram, get_proc_address);
-    INIT_FUNC(dispatch, glDeleteProgram, get_proc_address);
-    INIT_FUNC(dispatch, glCreateShader, get_proc_address);
-    INIT_FUNC(dispatch, glCompileShader, get_proc_address);
-    INIT_FUNC(dispatch, glAttachShader, get_proc_address);
-    INIT_FUNC(dispatch, glDeleteShader, get_proc_address);
-    INIT_FUNC(dispatch, glGetShaderiv, get_proc_address);
-    INIT_FUNC(dispatch, glGetShaderInfoLog, get_proc_address);
-    INIT_FUNC(dispatch, glGetProgramiv, get_proc_address);
-    INIT_FUNC(dispatch, glGetProgramInfoLog, get_proc_address);
-    INIT_FUNC(dispatch, glGetUniformLocation, get_proc_address);
-
-    return TRUE;
- fail:
-    return FALSE;
-}
diff --git a/glamor/glamor_gl_dispatch.h b/glamor/glamor_gl_dispatch.h
deleted file mode 100644
index 63790b4..0000000
--- a/glamor/glamor_gl_dispatch.h
+++ /dev/null
@@ -1,128 +0,0 @@
-typedef struct glamor_gl_dispatch {
-    /* Transformation functions */
-    void (*glMatrixMode) (GLenum mode);
-    void (*glLoadIdentity) (void);
-    void (*glViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
-    /* Drawing functions */
-    void (*glRasterPos2i) (GLint x, GLint y);
-
-    /* Vertex Array */
-    void (*glDrawArrays) (GLenum mode, GLint first, GLsizei count);
-
-    /* Elements Array */
-    void (*glDrawElements) (GLenum mode, GLsizei count, GLenum type,
-                            const GLvoid * indices);
-    void (*glDrawRangeElements) (GLenum mode, GLuint start, GLuint end,
-                                 GLsizei count, GLenum type,
-                                 const GLvoid * indices);
-
-    /* Raster functions */
-    void (*glReadPixels) (GLint x, GLint y,
-                          GLsizei width, GLsizei height,
-                          GLenum format, GLenum type, GLvoid * pixels);
-
-    void (*glDrawPixels) (GLsizei width, GLsizei height,
-                          GLenum format, GLenum type, const GLvoid * pixels);
-    void (*glPixelStorei) (GLenum pname, GLint param);
-    /* Texture Mapping */
-
-    void (*glTexParameteri) (GLenum target, GLenum pname, GLint param);
-    void (*glTexImage2D) (GLenum target, GLint level,
-                          GLint internalFormat,
-                          GLsizei width, GLsizei height,
-                          GLint border, GLenum format, GLenum type,
-                          const GLvoid * pixels);
-    /* 1.1 */
-    void (*glGenTextures) (GLsizei n, GLuint * textures);
-    void (*glDeleteTextures) (GLsizei n, const GLuint * textures);
-    void (*glBindTexture) (GLenum target, GLuint texture);
-    void (*glTexSubImage2D) (GLenum target, GLint level,
-                             GLint xoffset, GLint yoffset,
-                             GLsizei width, GLsizei height,
-                             GLenum format, GLenum type, const GLvoid * pixels);
-    /* MISC */
-    void (*glFlush) (void);
-    void (*glFinish) (void);
-    void (*glGetIntegerv) (GLenum pname, GLint * params);
-    const GLubyte *(*glGetString) (GLenum name);
-    void (*glScissor) (GLint x, GLint y, GLsizei width, GLsizei height);
-    void (*glEnable) (GLenum cap);
-    void (*glDisable) (GLenum cap);
-    void (*glBlendFunc) (GLenum sfactor, GLenum dfactor);
-    void (*glLogicOp) (GLenum opcode);
-
-    /* 1.3 */
-    void (*glActiveTexture) (GLenum texture);
-
-    /* GL Extentions */
-    void (*glGenBuffers) (GLsizei n, GLuint * buffers);
-    void (*glBufferData) (GLenum target, GLsizeiptr size,
-                          const GLvoid * data, GLenum usage);
-    GLvoid *(*glMapBuffer) (GLenum target, GLenum access);
-    GLvoid *(*glMapBufferRange) (GLenum target, GLintptr offset,
-                                 GLsizeiptr length, GLbitfield access);
-     GLboolean(*glUnmapBuffer) (GLenum target);
-    void (*glBindBuffer) (GLenum target, GLuint buffer);
-    void (*glDeleteBuffers) (GLsizei n, const GLuint * buffers);
-
-    void (*glFramebufferTexture2D) (GLenum target, GLenum attachment,
-                                    GLenum textarget, GLuint texture,
-                                    GLint level);
-    void (*glBindFramebuffer) (GLenum target, GLuint framebuffer);
-    void (*glDeleteFramebuffers) (GLsizei n, const GLuint * framebuffers);
-    void (*glGenFramebuffers) (GLsizei n, GLuint * framebuffers);
-     GLenum(*glCheckFramebufferStatus) (GLenum target);
-    void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1,
-                               GLint srcY1, GLint dstX0, GLint dstY0,
-                               GLint dstX1, GLint dstY1,
-                               GLbitfield mask, GLenum filter);
-
-    void (*glVertexAttribPointer) (GLuint index, GLint size,
-                                   GLenum type, GLboolean normalized,
-                                   GLsizei stride, const GLvoid * pointer);
-    void (*glDisableVertexAttribArray) (GLuint index);
-    void (*glEnableVertexAttribArray) (GLuint index);
-    void (*glBindAttribLocation) (GLuint program, GLuint index,
-                                  const GLchar * name);
-
-    void (*glLinkProgram) (GLuint program);
-    void (*glShaderSource) (GLuint shader, GLsizei count,
-                            const GLchar * *string, const GLint * length);
-    void (*glUseProgram) (GLuint program);
-    void (*glUniform1i) (GLint location, GLint v0);
-    void (*glUniform1f) (GLint location, GLfloat v0);
-    void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1,
-                         GLfloat v2, GLfloat v3);
-    void (*glUniform1fv) (GLint location, GLsizei count, const GLfloat * value);
-    void (*glUniform2fv) (GLint location, GLsizei count, const GLfloat * value);
-    void (*glUniform4fv) (GLint location, GLsizei count, const GLfloat * value);
-    void (*glUniformMatrix3fv) (GLint location, GLsizei count,
-                                GLboolean transpose, const GLfloat * value);
-     GLuint(*glCreateProgram) (void);
-     GLuint(*glDeleteProgram) (GLuint);
-     GLuint(*glCreateShader) (GLenum type);
-    void (*glCompileShader) (GLuint shader);
-    void (*glAttachShader) (GLuint program, GLuint shader);
-    void (*glDeleteShader) (GLuint shader);
-    void (*glGetShaderiv) (GLuint shader, GLenum pname, GLint * params);
-    void (*glGetShaderInfoLog) (GLuint shader, GLsizei bufSize,
-                                GLsizei * length, GLchar * infoLog);
-    void (*glGetProgramiv) (GLuint program, GLenum pname, GLint * params);
-    void (*glGetProgramInfoLog) (GLuint program, GLsizei bufSize,
-                                 GLsizei * length, GLchar * infoLog);
-     GLint(*glGetUniformLocation) (GLuint program, const GLchar * name);
-
-} glamor_gl_dispatch;
-
-typedef void *(*get_proc_address_t) (const char *);
-
-_X_EXPORT Bool
-
-glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch,
-                             int gl_version,
-                             get_proc_address_t get_proc_address);
-
-_X_EXPORT Bool
-
-glamor_gl_dispatch_init(ScreenPtr screen,
-                        struct glamor_gl_dispatch *dispatch, int gl_version);
diff --git a/glamor/glamor_glext.h b/glamor/glamor_glext.h
deleted file mode 100644
index 2a220c3..0000000
--- a/glamor/glamor_glext.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2001 Keith Packard
- * 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:
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- *
- */
-
-#ifdef GLAMOR_GLES2
-
-#define GL_BGRA                                 GL_BGRA_EXT
-#define GL_COLOR_INDEX                          0x1900
-#define GL_BITMAP                               0x1A00
-#define GL_UNSIGNED_INT_8_8_8_8                 0x8035
-#define GL_UNSIGNED_INT_8_8_8_8_REV             0x8367
-#define GL_UNSIGNED_INT_2_10_10_10_REV          0x8368
-#define GL_UNSIGNED_INT_10_10_10_2              0x8036
-#define GL_UNSIGNED_SHORT_5_6_5_REV             0x8364
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV           0x8366
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV           0x8365
-
-#define GL_PIXEL_PACK_BUFFER              0x88EB
-#define GL_PIXEL_UNPACK_BUFFER            0x88EC
-#define GL_CLAMP_TO_BORDER                0x812D
-
-#define GL_READ_WRITE                     0x88BA
-#define GL_READ_ONLY                      0x88B8
-#define GL_WRITE_ONLY                     0x88B9
-#define GL_STREAM_DRAW                    0x88E0
-#define GL_STREAM_READ                    0x88E1
-#define GL_PACK_ROW_LENGTH                      0x0D02
-#define GL_UNPACK_ROW_LENGTH                    0x0CF2
-
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
-
-#define GL_PACK_INVERT_MESA               0x8758
-#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020
-#define GL_MAP_READ_BIT                   0x0001
-#define GL_MAP_WRITE_BIT                  0x0002
-
-#endif
diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index 3586b33..c118f34 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -1274,14 +1274,12 @@ glamor_buffer_glyph(glamor_screen_private *glamor_priv,
             if (buffer->source == NULL)
                 buffer->source = source;
             if (glyphs_dst_mode == GLYPHS_DST_MODE_VIA_MASK_CACHE) {
-                glamor_gl_dispatch *dispatch;
-
                 /* mode 1 means we are using global mask cache,
                  * thus we have to composite from the cache picture
                  * to the cache picture, we need a flush here to make
                  * sure latter we get the corret glyphs data.*/
-                dispatch = glamor_get_dispatch(glamor_priv);
-                dispatch->glFlush();
+                glamor_get_dispatch(glamor_priv);
+                glFlush();
                 glamor_put_dispatch(glamor_priv);
             }
         }
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index df2ccb8..08df996 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -47,7 +47,6 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count,
                                    int use_array)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     char *gradient_fs = NULL;
     GLint fs_getcolor_prog;
@@ -177,18 +176,18 @@ _glamor_create_getcolor_fs_program(ScreenPtr screen, int stops_count,
         "}\n";
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     if (use_array) {
         XNFasprintf(&gradient_fs,
                     gradient_fs_getcolor, stops_count, stops_count);
         fs_getcolor_prog =
-            glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, gradient_fs);
+            glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
         free(gradient_fs);
     }
     else {
         fs_getcolor_prog =
-            glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER,
+            glamor_compile_glsl_prog(GL_FRAGMENT_SHADER,
                                      gradient_fs_getcolor_no_array);
     }
 
@@ -200,7 +199,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
                                        int dyn_gen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     int index;
 
     GLint gradient_prog = 0;
@@ -355,42 +353,37 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
         return;
     }
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) {
-        dispatch->glDeleteShader(glamor_priv->
-                                 radial_gradient_shaders
-                                 [SHADER_GRADIENT_VS_PROG][2]);
+        glDeleteShader(glamor_priv->radial_gradient_shaders
+                       [SHADER_GRADIENT_VS_PROG][2]);
         glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0;
 
-        dispatch->glDeleteShader(glamor_priv->
-                                 radial_gradient_shaders
-                                 [SHADER_GRADIENT_FS_MAIN_PROG][2]);
+        glDeleteShader(glamor_priv->radial_gradient_shaders
+                       [SHADER_GRADIENT_FS_MAIN_PROG][2]);
         glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] =
             0;
 
-        dispatch->glDeleteShader(glamor_priv->
-                                 radial_gradient_shaders
-                                 [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]);
+        glDeleteShader(glamor_priv->radial_gradient_shaders
+                       [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]);
         glamor_priv->
             radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0;
 
-        dispatch->glDeleteProgram(glamor_priv->
-                                  gradient_prog[SHADER_GRADIENT_RADIAL][2]);
+        glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]);
         glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2] = 0;
     }
 
-    gradient_prog = dispatch->glCreateProgram();
+    gradient_prog = glCreateProgram();
 
-    vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, gradient_vs);
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, gradient_vs);
 
     XNFasprintf(&gradient_fs,
                 gradient_radial_fs_template,
                 PIXMAN_REPEAT_NONE, PIXMAN_REPEAT_NORMAL,
                 PIXMAN_REPEAT_REFLECT);
 
-    fs_main_prog = glamor_compile_glsl_prog(dispatch,
-                                            GL_FRAGMENT_SHADER, gradient_fs);
+    fs_main_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
 
     free(gradient_fs);
 
@@ -398,18 +391,16 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
         _glamor_create_getcolor_fs_program(screen, stops_count,
                                            (stops_count > 0));
 
-    dispatch->glAttachShader(gradient_prog, vs_prog);
-    dispatch->glAttachShader(gradient_prog, fs_getcolor_prog);
-    dispatch->glAttachShader(gradient_prog, fs_main_prog);
+    glAttachShader(gradient_prog, vs_prog);
+    glAttachShader(gradient_prog, fs_getcolor_prog);
+    glAttachShader(gradient_prog, fs_main_prog);
 
-    dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS,
-                                   "v_positionsition");
-    dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE,
-                                   "v_texcoord");
+    glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_positionsition");
+    glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
 
-    glamor_link_glsl_prog(dispatch, gradient_prog);
+    glamor_link_glsl_prog(gradient_prog);
 
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
 
     if (dyn_gen) {
         index = 2;
@@ -439,7 +430,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
                                        int dyn_gen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     int index = 0;
     GLint gradient_prog = 0;
@@ -596,58 +586,51 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
         return;
     }
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]) {
-        dispatch->glDeleteShader(glamor_priv->
-                                 linear_gradient_shaders
-                                 [SHADER_GRADIENT_VS_PROG][2]);
+        glDeleteShader(glamor_priv->linear_gradient_shaders
+                       [SHADER_GRADIENT_VS_PROG][2]);
         glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][2] = 0;
 
-        dispatch->glDeleteShader(glamor_priv->
-                                 linear_gradient_shaders
-                                 [SHADER_GRADIENT_FS_MAIN_PROG][2]);
+        glDeleteShader(glamor_priv->linear_gradient_shaders
+                       [SHADER_GRADIENT_FS_MAIN_PROG][2]);
         glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][2] =
             0;
 
-        dispatch->glDeleteShader(glamor_priv->
-                                 linear_gradient_shaders
-                                 [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]);
+        glDeleteShader(glamor_priv->linear_gradient_shaders
+                       [SHADER_GRADIENT_FS_GETCOLOR_PROG][2]);
         glamor_priv->
             linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][2] = 0;
 
-        dispatch->glDeleteProgram(glamor_priv->
-                                  gradient_prog[SHADER_GRADIENT_LINEAR][2]);
+        glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2]);
         glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][2] = 0;
     }
 
-    gradient_prog = dispatch->glCreateProgram();
+    gradient_prog = glCreateProgram();
 
-    vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, gradient_vs);
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, gradient_vs);
 
     XNFasprintf(&gradient_fs,
                 gradient_fs_template,
                 PIXMAN_REPEAT_NORMAL, PIXMAN_REPEAT_REFLECT);
 
-    fs_main_prog = glamor_compile_glsl_prog(dispatch,
-                                            GL_FRAGMENT_SHADER, gradient_fs);
+    fs_main_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, gradient_fs);
     free(gradient_fs);
 
     fs_getcolor_prog =
         _glamor_create_getcolor_fs_program(screen, stops_count,
                                            (stops_count > 0));
 
-    dispatch->glAttachShader(gradient_prog, vs_prog);
-    dispatch->glAttachShader(gradient_prog, fs_getcolor_prog);
-    dispatch->glAttachShader(gradient_prog, fs_main_prog);
+    glAttachShader(gradient_prog, vs_prog);
+    glAttachShader(gradient_prog, fs_getcolor_prog);
+    glAttachShader(gradient_prog, fs_main_prog);
 
-    dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS,
-                                   "v_position");
-    dispatch->glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE,
-                                   "v_texcoord");
+    glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_POS, "v_position");
+    glBindAttribLocation(gradient_prog, GLAMOR_VERTEX_SOURCE, "v_texcoord");
 
-    glamor_link_glsl_prog(dispatch, gradient_prog);
+    glamor_link_glsl_prog(gradient_prog);
 
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
 
     if (dyn_gen) {
         index = 2;
@@ -709,56 +692,49 @@ void
 glamor_fini_gradient_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     int i = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     for (i = 0; i < 3; i++) {
         /* Linear Gradient */
         if (glamor_priv->linear_gradient_shaders[SHADER_GRADIENT_VS_PROG][i])
-            dispatch->glDeleteShader(glamor_priv->
-                                     linear_gradient_shaders
-                                     [SHADER_GRADIENT_VS_PROG][i]);
+            glDeleteShader(glamor_priv->linear_gradient_shaders
+                           [SHADER_GRADIENT_VS_PROG][i]);
 
         if (glamor_priv->
             linear_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i])
-            dispatch->glDeleteShader(glamor_priv->
-                                     linear_gradient_shaders
-                                     [SHADER_GRADIENT_FS_MAIN_PROG][i]);
+            glDeleteShader(glamor_priv->linear_gradient_shaders
+                           [SHADER_GRADIENT_FS_MAIN_PROG][i]);
 
         if (glamor_priv->
             linear_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i])
-            dispatch->glDeleteShader(glamor_priv->
-                                     linear_gradient_shaders
-                                     [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]);
+            glDeleteShader(glamor_priv->linear_gradient_shaders
+                           [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]);
 
         if (glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][i])
-            dispatch->glDeleteProgram(glamor_priv->
-                                      gradient_prog[SHADER_GRADIENT_LINEAR][i]);
+            glDeleteProgram(glamor_priv->gradient_prog
+                            [SHADER_GRADIENT_LINEAR][i]);
 
         /* Radial Gradient */
         if (glamor_priv->radial_gradient_shaders[SHADER_GRADIENT_VS_PROG][i])
-            dispatch->glDeleteShader(glamor_priv->
-                                     radial_gradient_shaders
-                                     [SHADER_GRADIENT_VS_PROG][i]);
+            glDeleteShader(glamor_priv->radial_gradient_shaders
+                           [SHADER_GRADIENT_VS_PROG][i]);
 
         if (glamor_priv->
             radial_gradient_shaders[SHADER_GRADIENT_FS_MAIN_PROG][i])
-            dispatch->glDeleteShader(glamor_priv->
-                                     radial_gradient_shaders
-                                     [SHADER_GRADIENT_FS_MAIN_PROG][i]);
+            glDeleteShader(glamor_priv->radial_gradient_shaders
+                           [SHADER_GRADIENT_FS_MAIN_PROG][i]);
 
         if (glamor_priv->
             radial_gradient_shaders[SHADER_GRADIENT_FS_GETCOLOR_PROG][i])
-            dispatch->glDeleteShader(glamor_priv->
-                                     radial_gradient_shaders
-                                     [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]);
+            glDeleteShader(glamor_priv->radial_gradient_shaders
+                           [SHADER_GRADIENT_FS_GETCOLOR_PROG][i]);
 
         if (glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][i])
-            dispatch->glDeleteProgram(glamor_priv->
-                                      gradient_prog[SHADER_GRADIENT_RADIAL][i]);
+            glDeleteProgram(glamor_priv->gradient_prog
+                            [SHADER_GRADIENT_RADIAL][i]);
     }
 
     glamor_put_dispatch(glamor_priv);
@@ -835,7 +811,6 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
 {
     glamor_pixmap_private *pixmap_priv;
     PixmapPtr pixmap = NULL;
-    glamor_gl_dispatch *dispatch = NULL;
 
     pixmap = glamor_get_drawable_pixmap(dst_picture->pDrawable);
     pixmap_priv = glamor_get_pixmap_private(pixmap);
@@ -893,15 +868,15 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
            tex_vertices[0], tex_vertices[1], tex_vertices[2], tex_vertices[3],
            tex_vertices[4], tex_vertices[5], tex_vertices[6], tex_vertices[7]);
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 0, vertices);
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
-                                    GL_FALSE, 0, tex_vertices);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, 0, vertices);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
+                          GL_FALSE, 0, tex_vertices);
 
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
     glamor_put_dispatch(glamor_priv);
 
@@ -996,7 +971,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
                                         PictFormatShort format)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     PicturePtr dst_picture = NULL;
     PixmapPtr pixmap = NULL;
     GLint gradient_prog = 0;
@@ -1047,7 +1021,7 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     GLint r2_uniform_location = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     /* Create a pixmap with VBO. */
     pixmap = glamor_create_pixmap(screen,
@@ -1088,77 +1062,74 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     }
 
     /* Bind all the uniform vars . */
-    transform_mat_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "transform_mat");
-    repeat_type_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "repeat_type");
-    n_stop_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "n_stop");
-    A_value_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "A_value");
-    repeat_type_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "repeat_type");
-    c1_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "c1");
-    r1_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "r1");
-    c2_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "c2");
-    r2_uniform_location = dispatch->glGetUniformLocation(gradient_prog, "r2");
+    transform_mat_uniform_location = glGetUniformLocation(gradient_prog,
+                                                          "transform_mat");
+    repeat_type_uniform_location = glGetUniformLocation(gradient_prog,
+                                                        "repeat_type");
+    n_stop_uniform_location = glGetUniformLocation(gradient_prog, "n_stop");
+    A_value_uniform_location = glGetUniformLocation(gradient_prog, "A_value");
+    repeat_type_uniform_location =glGetUniformLocation(gradient_prog,
+                                                       "repeat_type");
+    c1_uniform_location = glGetUniformLocation(gradient_prog, "c1");
+    r1_uniform_location = glGetUniformLocation(gradient_prog, "r1");
+    c2_uniform_location = glGetUniformLocation(gradient_prog, "c2");
+    r2_uniform_location = glGetUniformLocation(gradient_prog, "r2");
 
     if (src_picture->pSourcePict->radial.nstops + 2 <= RADIAL_SMALL_STOPS) {
         stop0_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop0");
+            glGetUniformLocation(gradient_prog, "stop0");
         stop1_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop1");
+            glGetUniformLocation(gradient_prog, "stop1");
         stop2_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop2");
+            glGetUniformLocation(gradient_prog, "stop2");
         stop3_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop3");
+            glGetUniformLocation(gradient_prog, "stop3");
         stop4_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop4");
+            glGetUniformLocation(gradient_prog, "stop4");
         stop5_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop5");
+            glGetUniformLocation(gradient_prog, "stop5");
         stop6_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop6");
+            glGetUniformLocation(gradient_prog, "stop6");
         stop7_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop7");
+            glGetUniformLocation(gradient_prog, "stop7");
 
         stop_color0_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color0");
+            glGetUniformLocation(gradient_prog, "stop_color0");
         stop_color1_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color1");
+            glGetUniformLocation(gradient_prog, "stop_color1");
         stop_color2_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color2");
+            glGetUniformLocation(gradient_prog, "stop_color2");
         stop_color3_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color3");
+            glGetUniformLocation(gradient_prog, "stop_color3");
         stop_color4_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color4");
+            glGetUniformLocation(gradient_prog, "stop_color4");
         stop_color5_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color5");
+            glGetUniformLocation(gradient_prog, "stop_color5");
         stop_color6_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color6");
+            glGetUniformLocation(gradient_prog, "stop_color6");
         stop_color7_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color7");
+            glGetUniformLocation(gradient_prog, "stop_color7");
     }
     else {
         stops_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stops");
+            glGetUniformLocation(gradient_prog, "stops");
         stop_colors_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_colors");
+            glGetUniformLocation(gradient_prog, "stop_colors");
     }
 
-    dispatch->glUseProgram(gradient_prog);
+    glUseProgram(gradient_prog);
 
-    dispatch->glUniform1i(repeat_type_uniform_location,
-                          src_picture->repeatType);
+    glUniform1i(repeat_type_uniform_location, src_picture->repeatType);
 
     if (src_picture->transform) {
         _glamor_gradient_convert_trans_matrix(src_picture->transform,
                                               transform_mat, width, height, 0);
-        dispatch->glUniformMatrix3fv(transform_mat_uniform_location,
-                                     1, 1, &transform_mat[0][0]);
+        glUniformMatrix3fv(transform_mat_uniform_location,
+                           1, 1, &transform_mat[0][0]);
     }
     else {
-        dispatch->glUniformMatrix3fv(transform_mat_uniform_location,
-                                     1, 1, &identity_mat[0][0]);
+        glUniformMatrix3fv(transform_mat_uniform_location,
+                           1, 1, &identity_mat[0][0]);
     }
 
     if (!_glamor_gradient_set_pixmap_destination
@@ -1193,54 +1164,53 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     if (src_picture->pSourcePict->linear.nstops + 2 <= RADIAL_SMALL_STOPS) {
         int j = 0;
 
-        dispatch->glUniform4f(stop_color0_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color0_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color1_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color1_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color2_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color2_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color3_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color3_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color4_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color4_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color5_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color5_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color6_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color6_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color7_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color7_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
 
         j = 0;
-        dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]);
-        dispatch->glUniform1i(n_stop_uniform_location, count);
+        glUniform1f(stop0_uniform_location, n_stops[j++]);
+        glUniform1f(stop1_uniform_location, n_stops[j++]);
+        glUniform1f(stop2_uniform_location, n_stops[j++]);
+        glUniform1f(stop3_uniform_location, n_stops[j++]);
+        glUniform1f(stop4_uniform_location, n_stops[j++]);
+        glUniform1f(stop5_uniform_location, n_stops[j++]);
+        glUniform1f(stop6_uniform_location, n_stops[j++]);
+        glUniform1f(stop7_uniform_location, n_stops[j++]);
+        glUniform1i(n_stop_uniform_location, count);
     }
     else {
-        dispatch->glUniform4fv(stop_colors_uniform_location, count,
-                               stop_colors);
-        dispatch->glUniform1fv(stops_uniform_location, count, n_stops);
-        dispatch->glUniform1i(n_stop_uniform_location, count);
+        glUniform4fv(stop_colors_uniform_location, count, stop_colors);
+        glUniform1fv(stops_uniform_location, count, n_stops);
+        glUniform1i(n_stop_uniform_location, count);
     }
 
     c1x = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c1.x);
@@ -1255,25 +1225,25 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
 
     glamor_set_circle_centre(width, height, c1x, c1y, glamor_priv->yInverted,
                              cxy);
-    dispatch->glUniform2fv(c1_uniform_location, 1, cxy);
-    dispatch->glUniform1f(r1_uniform_location, r1);
+    glUniform2fv(c1_uniform_location, 1, cxy);
+    glUniform1f(r1_uniform_location, r1);
 
     glamor_set_circle_centre(width, height, c2x, c2y, glamor_priv->yInverted,
                              cxy);
-    dispatch->glUniform2fv(c2_uniform_location, 1, cxy);
-    dispatch->glUniform1f(r2_uniform_location, r2);
+    glUniform2fv(c2_uniform_location, 1, cxy);
+    glUniform1f(r2_uniform_location, r2);
 
     A_value =
         (c2x - c1x) * (c2x - c1x) + (c2y - c1y) * (c2y - c1y) - (r2 -
                                                                  r1) * (r2 -
                                                                         r1);
-    dispatch->glUniform1f(A_value_uniform_location, A_value);
+    glUniform1f(A_value_uniform_location, A_value);
 
     DEBUGF("C1:(%f, %f) R1:%f\nC2:(%f, %f) R2:%f\nA = %f\n",
            c1x, c1y, r1, c2x, c2y, r2, A_value);
 
     /* Now rendering. */
-    dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 
     /* Do the clear logic. */
     if (stops_count > RADIAL_SMALL_STOPS) {
@@ -1281,12 +1251,12 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
         free(stop_colors);
     }
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glUseProgram(0);
 
     glamor_put_dispatch(glamor_priv);
     return dst_picture;
@@ -1303,12 +1273,12 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
             free(stop_colors);
     }
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
     return NULL;
 }
@@ -1321,7 +1291,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
                                         PictFormatShort format)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     PicturePtr dst_picture = NULL;
     PixmapPtr pixmap = NULL;
     GLint gradient_prog = 0;
@@ -1374,7 +1343,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     GLint pt_distance_uniform_location = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     /* Create a pixmap with VBO. */
     pixmap = glamor_create_pixmap(screen,
@@ -1417,79 +1386,78 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
 
     /* Bind all the uniform vars . */
     n_stop_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "n_stop");
+        glGetUniformLocation(gradient_prog, "n_stop");
     pt_slope_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "pt_slope");
+        glGetUniformLocation(gradient_prog, "pt_slope");
     repeat_type_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "repeat_type");
+        glGetUniformLocation(gradient_prog, "repeat_type");
     hor_ver_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "hor_ver");
+        glGetUniformLocation(gradient_prog, "hor_ver");
     transform_mat_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "transform_mat");
+        glGetUniformLocation(gradient_prog, "transform_mat");
     cos_val_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "cos_val");
+        glGetUniformLocation(gradient_prog, "cos_val");
     p1_distance_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "p1_distance");
+        glGetUniformLocation(gradient_prog, "p1_distance");
     pt_distance_uniform_location =
-        dispatch->glGetUniformLocation(gradient_prog, "pt_distance");
+        glGetUniformLocation(gradient_prog, "pt_distance");
 
     if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) {
         stop0_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop0");
+            glGetUniformLocation(gradient_prog, "stop0");
         stop1_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop1");
+            glGetUniformLocation(gradient_prog, "stop1");
         stop2_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop2");
+            glGetUniformLocation(gradient_prog, "stop2");
         stop3_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop3");
+            glGetUniformLocation(gradient_prog, "stop3");
         stop4_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop4");
+            glGetUniformLocation(gradient_prog, "stop4");
         stop5_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop5");
+            glGetUniformLocation(gradient_prog, "stop5");
         stop6_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop6");
+            glGetUniformLocation(gradient_prog, "stop6");
         stop7_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop7");
+            glGetUniformLocation(gradient_prog, "stop7");
 
         stop_color0_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color0");
+            glGetUniformLocation(gradient_prog, "stop_color0");
         stop_color1_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color1");
+            glGetUniformLocation(gradient_prog, "stop_color1");
         stop_color2_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color2");
+            glGetUniformLocation(gradient_prog, "stop_color2");
         stop_color3_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color3");
+            glGetUniformLocation(gradient_prog, "stop_color3");
         stop_color4_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color4");
+            glGetUniformLocation(gradient_prog, "stop_color4");
         stop_color5_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color5");
+            glGetUniformLocation(gradient_prog, "stop_color5");
         stop_color6_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color6");
+            glGetUniformLocation(gradient_prog, "stop_color6");
         stop_color7_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_color7");
+            glGetUniformLocation(gradient_prog, "stop_color7");
     }
     else {
         stops_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stops");
+            glGetUniformLocation(gradient_prog, "stops");
         stop_colors_uniform_location =
-            dispatch->glGetUniformLocation(gradient_prog, "stop_colors");
+            glGetUniformLocation(gradient_prog, "stop_colors");
     }
 
-    dispatch->glUseProgram(gradient_prog);
+    glUseProgram(gradient_prog);
 
-    dispatch->glUniform1i(repeat_type_uniform_location,
-                          src_picture->repeatType);
+    glUniform1i(repeat_type_uniform_location, src_picture->repeatType);
 
     /* set the transform matrix. */
     if (src_picture->transform) {
         _glamor_gradient_convert_trans_matrix(src_picture->transform,
                                               transform_mat, width, height, 1);
-        dispatch->glUniformMatrix3fv(transform_mat_uniform_location,
-                                     1, 1, &transform_mat[0][0]);
+        glUniformMatrix3fv(transform_mat_uniform_location,
+                           1, 1, &transform_mat[0][0]);
     }
     else {
-        dispatch->glUniformMatrix3fv(transform_mat_uniform_location,
-                                     1, 1, &identity_mat[0][0]);
+        glUniformMatrix3fv(transform_mat_uniform_location,
+                           1, 1, &identity_mat[0][0]);
     }
 
     if (!_glamor_gradient_set_pixmap_destination
@@ -1547,66 +1515,65 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     if (src_picture->pSourcePict->linear.nstops + 2 <= LINEAR_SMALL_STOPS) {
         int j = 0;
 
-        dispatch->glUniform4f(stop_color0_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color0_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color1_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color1_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color2_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color2_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color3_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color3_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color4_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color4_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color5_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color5_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color6_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color6_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
         j++;
-        dispatch->glUniform4f(stop_color7_uniform_location,
-                              stop_colors[4 * j + 0], stop_colors[4 * j + 1],
-                              stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
+        glUniform4f(stop_color7_uniform_location,
+                    stop_colors[4 * j + 0], stop_colors[4 * j + 1],
+                    stop_colors[4 * j + 2], stop_colors[4 * j + 3]);
 
         j = 0;
-        dispatch->glUniform1f(stop0_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop1_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop2_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop3_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop4_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop5_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop6_uniform_location, n_stops[j++]);
-        dispatch->glUniform1f(stop7_uniform_location, n_stops[j++]);
-
-        dispatch->glUniform1i(n_stop_uniform_location, count);
+        glUniform1f(stop0_uniform_location, n_stops[j++]);
+        glUniform1f(stop1_uniform_location, n_stops[j++]);
+        glUniform1f(stop2_uniform_location, n_stops[j++]);
+        glUniform1f(stop3_uniform_location, n_stops[j++]);
+        glUniform1f(stop4_uniform_location, n_stops[j++]);
+        glUniform1f(stop5_uniform_location, n_stops[j++]);
+        glUniform1f(stop6_uniform_location, n_stops[j++]);
+        glUniform1f(stop7_uniform_location, n_stops[j++]);
+
+        glUniform1i(n_stop_uniform_location, count);
     }
     else {
-        dispatch->glUniform4fv(stop_colors_uniform_location, count,
-                               stop_colors);
-        dispatch->glUniform1fv(stops_uniform_location, count, n_stops);
-        dispatch->glUniform1i(n_stop_uniform_location, count);
+        glUniform4fv(stop_colors_uniform_location, count, stop_colors);
+        glUniform1fv(stops_uniform_location, count, n_stops);
+        glUniform1i(n_stop_uniform_location, count);
     }
 
     if (src_picture->pSourcePict->linear.p2.y == src_picture->pSourcePict->linear.p1.y) {       // The horizontal case.
-        dispatch->glUniform1i(hor_ver_uniform_location, 1);
+        glUniform1i(hor_ver_uniform_location, 1);
         DEBUGF("p1.y: %f, p2.y: %f, enter the horizontal case\n",
                pt1[1], pt2[1]);
 
         p1_distance = pt1[0];
         pt_distance = (pt2[0] - p1_distance);
-        dispatch->glUniform1f(p1_distance_uniform_location, p1_distance);
-        dispatch->glUniform1f(pt_distance_uniform_location, pt_distance);
+        glUniform1f(p1_distance_uniform_location, p1_distance);
+        glUniform1f(pt_distance_uniform_location, pt_distance);
     }
     else {
         /* The slope need to compute here. In shader, the viewport set will change
@@ -1616,20 +1583,20 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
             (float) (src_picture->pSourcePict->linear.p2.y
                      - src_picture->pSourcePict->linear.p1.y);
         slope = slope * yscale / xscale;
-        dispatch->glUniform1f(pt_slope_uniform_location, slope);
-        dispatch->glUniform1i(hor_ver_uniform_location, 0);
+        glUniform1f(pt_slope_uniform_location, slope);
+        glUniform1i(hor_ver_uniform_location, 0);
 
         cos_val = sqrt(1.0 / (slope * slope + 1.0));
-        dispatch->glUniform1f(cos_val_uniform_location, cos_val);
+        glUniform1f(cos_val_uniform_location, cos_val);
 
         p1_distance = (pt1[1] - pt1[0] * slope) * cos_val;
         pt_distance = (pt2[1] - pt2[0] * slope) * cos_val - p1_distance;
-        dispatch->glUniform1f(p1_distance_uniform_location, p1_distance);
-        dispatch->glUniform1f(pt_distance_uniform_location, pt_distance);
+        glUniform1f(p1_distance_uniform_location, p1_distance);
+        glUniform1f(pt_distance_uniform_location, pt_distance);
     }
 
     /* Now rendering. */
-    dispatch->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 
     /* Do the clear logic. */
     if (stops_count > LINEAR_SMALL_STOPS) {
@@ -1637,12 +1604,12 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
         free(stop_colors);
     }
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glUseProgram(0);
 
     glamor_put_dispatch(glamor_priv);
     return dst_picture;
@@ -1659,12 +1626,12 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
             free(stop_colors);
     }
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
     return NULL;
 }
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index f7de59c..7f152fc 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -66,16 +66,16 @@ void
 glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0,
                                   int width, int height)
 {
-    glamor_gl_dispatch *dispatch = glamor_get_dispatch(fbo->glamor_priv);
+    glamor_get_dispatch(fbo->glamor_priv);
 
-    dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
 #ifndef GLAMOR_GLES2
-    dispatch->glMatrixMode(GL_PROJECTION);
-    dispatch->glLoadIdentity();
-    dispatch->glMatrixMode(GL_MODELVIEW);
-    dispatch->glLoadIdentity();
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
 #endif
-    dispatch->glViewport(x0, y0, width, height);
+    glViewport(x0, y0, width, height);
 
     glamor_put_dispatch(fbo->glamor_priv);
 }
@@ -121,59 +121,59 @@ glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask)
 }
 
 Bool
-glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu)
+glamor_set_alu(unsigned char alu)
 {
 #ifndef GLAMOR_GLES2
     if (alu == GXcopy) {
-        dispatch->glDisable(GL_COLOR_LOGIC_OP);
+        glDisable(GL_COLOR_LOGIC_OP);
         return TRUE;
     }
-    dispatch->glEnable(GL_COLOR_LOGIC_OP);
+    glEnable(GL_COLOR_LOGIC_OP);
     switch (alu) {
     case GXclear:
-        dispatch->glLogicOp(GL_CLEAR);
+        glLogicOp(GL_CLEAR);
         break;
     case GXand:
-        dispatch->glLogicOp(GL_AND);
+        glLogicOp(GL_AND);
         break;
     case GXandReverse:
-        dispatch->glLogicOp(GL_AND_REVERSE);
+        glLogicOp(GL_AND_REVERSE);
         break;
     case GXandInverted:
-        dispatch->glLogicOp(GL_AND_INVERTED);
+        glLogicOp(GL_AND_INVERTED);
         break;
     case GXnoop:
-        dispatch->glLogicOp(GL_NOOP);
+        glLogicOp(GL_NOOP);
         break;
     case GXxor:
-        dispatch->glLogicOp(GL_XOR);
+        glLogicOp(GL_XOR);
         break;
     case GXor:
-        dispatch->glLogicOp(GL_OR);
+        glLogicOp(GL_OR);
         break;
     case GXnor:
-        dispatch->glLogicOp(GL_NOR);
+        glLogicOp(GL_NOR);
         break;
     case GXequiv:
-        dispatch->glLogicOp(GL_EQUIV);
+        glLogicOp(GL_EQUIV);
         break;
     case GXinvert:
-        dispatch->glLogicOp(GL_INVERT);
+        glLogicOp(GL_INVERT);
         break;
     case GXorReverse:
-        dispatch->glLogicOp(GL_OR_REVERSE);
+        glLogicOp(GL_OR_REVERSE);
         break;
     case GXcopyInverted:
-        dispatch->glLogicOp(GL_COPY_INVERTED);
+        glLogicOp(GL_COPY_INVERTED);
         break;
     case GXorInverted:
-        dispatch->glLogicOp(GL_OR_INVERTED);
+        glLogicOp(GL_OR_INVERTED);
         break;
     case GXnand:
-        dispatch->glLogicOp(GL_NAND);
+        glLogicOp(GL_NAND);
         break;
     case GXset:
-        dispatch->glLogicOp(GL_SET);
+        glLogicOp(GL_SET);
         break;
     default:
         glamor_fallback("unsupported alu %x\n", alu);
@@ -397,13 +397,12 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
 {
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
-    glamor_gl_dispatch *dispatch;
     int non_sub = 0;
     unsigned int iformat = 0;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
     if (*tex == 0) {
-        dispatch->glGenTextures(1, tex);
+        glGenTextures(1, tex);
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
             gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
         else
@@ -412,22 +411,20 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
         assert(x == 0 && y == 0);
     }
 
-    dispatch->glBindTexture(GL_TEXTURE_2D, *tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glBindTexture(GL_TEXTURE_2D, *tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
     if (bits == NULL)
-        dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
     if (non_sub)
-        dispatch->glTexImage2D(GL_TEXTURE_2D,
-                               0, iformat, w, h, 0, format, type, bits);
+        glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits);
     else
-        dispatch->glTexSubImage2D(GL_TEXTURE_2D,
-                                  0, x, y, w, h, format, type, bits);
+        glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits);
 
     if (bits == NULL)
-        dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -440,7 +437,6 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
-    glamor_gl_dispatch *dispatch;
     static float vertices[8];
 
     static float texcoords[8] = { 0, 1,
@@ -526,40 +522,39 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
                                  x + w, y + h,
                                  glamor_priv->yInverted, vertices);
     /* Slow path, we need to flip y or wire alpha to 1. */
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), vertices);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), ptexcoords);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glamor_get_dispatch(glamor_priv);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, 2 * sizeof(float), vertices);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
+                          GL_FALSE, 2 * sizeof(float), ptexcoords);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
     __glamor_upload_pixmap_to_texture(pixmap, &tex,
                                       format, type, 0, 0, w, h, bits, pbo);
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glBindTexture(GL_TEXTURE_2D, tex);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, tex);
 
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 #ifndef GLAMOR_GLES2
-    dispatch->glEnable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_2D);
 #endif
-    dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
-    dispatch->glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
-    dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],
-                          swap_rb);
+    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
+    glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
+    glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
 
-    dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
 #ifndef GLAMOR_GLES2
-    dispatch->glDisable(GL_TEXTURE_2D);
+    glDisable(GL_TEXTURE_2D);
 #endif
-    dispatch->glUseProgram(0);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glDeleteTextures(1, &tex);
-    dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDeleteTextures(1, &tex);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
     glamor_put_dispatch(glamor_priv);
 
@@ -831,7 +826,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
     glamor_screen_private *glamor_priv;
     ScreenPtr screen;
     glamor_pixmap_fbo *temp_fbo;
-    glamor_gl_dispatch *dispatch;
     float temp_xscale, temp_yscale, source_xscale, source_yscale;
     static float vertices[8];
     static float texcoords[8];
@@ -844,7 +838,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
     if (temp_fbo == NULL)
         return NULL;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
     temp_xscale = 1.0 / w;
     temp_yscale = 1.0 / h;
 
@@ -852,9 +846,9 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
                                  temp_xscale, temp_yscale, 0, 0, w, h,
                                  glamor_priv->yInverted, vertices);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), vertices);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), vertices);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale);
     glamor_set_normalize_tcoords(source_priv, source_xscale,
@@ -863,26 +857,25 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
                                  x + w, y + h,
                                  glamor_priv->yInverted, texcoords);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), texcoords);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), texcoords);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, source_priv->base.fbo->tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
     glamor_set_destination_pixmap_fbo(temp_fbo, 0, 0, w, h);
-    dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
-    dispatch->glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
-    dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],
-                          swap_rb);
+    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
+    glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
+    glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
 
-    dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
     return temp_fbo;
 }
@@ -905,7 +898,6 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
     void *data, *read;
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
-    glamor_gl_dispatch *dispatch;
     glamor_pixmap_fbo *temp_fbo = NULL;
     int need_post_conversion = 0;
     int need_free_data = 0;
@@ -964,56 +956,52 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         fbo_y_off = 0;
     }
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glPixelStorei(GL_PACK_ALIGNMENT, 4);
+    glamor_get_dispatch(glamor_priv);
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
     if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
 
         if (!glamor_priv->yInverted) {
             assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
-            dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 1);
+            glPixelStorei(GL_PACK_INVERT_MESA, 1);
         }
 
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) {
             assert(pbo > 0);
-            dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
-            dispatch->glBufferData(GL_PIXEL_PACK_BUFFER,
-                                   stride * h, NULL, gl_usage);
+            glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+            glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, gl_usage);
         }
 
-        dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type,
-                               data);
+        glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
 
         if (!glamor_priv->yInverted) {
             assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
-            dispatch->glPixelStorei(GL_PACK_INVERT_MESA, 0);
+            glPixelStorei(GL_PACK_INVERT_MESA, 0);
         }
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) {
-            bits = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
-            dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+            bits = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
+            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
         }
     }
     else {
         unsigned int temp_pbo;
         int yy;
 
-        dispatch = glamor_get_dispatch(glamor_priv);
-        dispatch->glGenBuffers(1, &temp_pbo);
-        dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, temp_pbo);
-        dispatch->glBufferData(GL_PIXEL_PACK_BUFFER,
-                               stride * h, NULL, GL_STREAM_READ);
-        dispatch->glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h,
-                               format, type, 0);
-        read = dispatch->glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
+        glamor_get_dispatch(glamor_priv);
+        glGenBuffers(1, &temp_pbo);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, temp_pbo);
+        glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, GL_STREAM_READ);
+        glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, 0);
+        read = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
         for (yy = 0; yy < pixmap->drawable.height; yy++)
             memcpy((char *) data + yy * stride,
                    (char *) read + (h - yy - 1) * stride, stride);
-        dispatch->glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
-        dispatch->glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-        dispatch->glDeleteBuffers(1, &temp_pbo);
+        glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+        glDeleteBuffers(1, &temp_pbo);
     }
 
-    dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
     glamor_put_dispatch(glamor_priv);
 
     if (need_post_conversion) {
@@ -1168,7 +1156,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
     void *data = NULL, *dst;
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
-    glamor_gl_dispatch *dispatch;
     int pbo = 0;
 
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
@@ -1189,9 +1176,9 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
         data = malloc(stride * pixmap->drawable.height);
     }
     else {
-        dispatch = glamor_get_dispatch(glamor_priv);
+        glamor_get_dispatch(glamor_priv);
         if (pixmap_priv->base.fbo->pbo == 0)
-            dispatch->glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
+            glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
         glamor_put_dispatch(glamor_priv);
         pbo = pixmap_priv->base.fbo->pbo;
     }
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index dc38730..8477091 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -35,15 +35,11 @@
 #endif
 #include "glamor.h"
 
-#ifdef GLAMOR_GLES2
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
+#include <epoxy/gl.h>
 
+#ifdef GLAMOR_GLES2
 #define GLAMOR_DEFAULT_PRECISION   "precision mediump float;\n"
-#include "glamor_glext.h"
 #else
-#include <GL/gl.h>
-#include <GL/glext.h>
 #define GLAMOR_DEFAULT_PRECISION
 #endif
 
@@ -178,8 +174,6 @@ typedef struct {
     uint16_t evict;
 } glamor_glyph_cache_t;
 
-#include "glamor_gl_dispatch.h"
-
 struct glamor_saved_procs {
     CloseScreenProcPtr close_screen;
     CreateGCProcPtr create_gc;
@@ -220,7 +214,6 @@ struct glamor_saved_procs {
 #define RENDER_IDEL_MAX 32
 
 typedef struct glamor_screen_private {
-    struct glamor_gl_dispatch _dispatch;
     int yInverted;
     unsigned int tick;
     enum glamor_gl_flavor gl_flavor;
@@ -583,9 +576,8 @@ Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
                     unsigned char alu, unsigned long planemask,
                     unsigned long fg_pixel, unsigned long bg_pixel,
                     int stipple_x, int stipple_y);
-GLint glamor_compile_glsl_prog(glamor_gl_dispatch *dispatch, GLenum type,
-                               const char *source);
-void glamor_link_glsl_prog(glamor_gl_dispatch *dispatch, GLint prog);
+GLint glamor_compile_glsl_prog(GLenum type, const char *source);
+void glamor_link_glsl_prog(GLint prog);
 void glamor_get_color_4f_from_pixel(PixmapPtr pixmap,
                                     unsigned long fg_pixel, GLfloat *color);
 
@@ -604,7 +596,7 @@ glamor_pixmap_fbo *glamor_es2_pixmap_read_prepare(PixmapPtr source, int x,
                                                   int no_alpha, int revert,
                                                   int swap_rb);
 
-Bool glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu);
+Bool glamor_set_alu(unsigned char alu);
 Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask);
 RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c
index 6b25bec..60ccd67 100644
--- a/glamor/glamor_putimage.c
+++ b/glamor/glamor_putimage.c
@@ -67,27 +67,26 @@ glamor_init_putimage_shaders(ScreenPtr screen)
     if (!GLEW_ARB_fragment_shader)
         return;
 
-    prog = dispatch->glCreateProgram();
+    prog = glCreateProgram();
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xybitmap_vs);
     fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xybitmap_fs);
-    dispatch->glAttachShader(prog, vs_prog);
-    dispatch->glAttachShader(prog, fs_prog);
+    glAttachShader(prog, vs_prog);
+    glAttachShader(prog, fs_prog);
     glamor_link_glsl_prog(prog);
 
-    dispatch->glUseProgram(prog);
-    sampler_uniform_location =
-        dispatch->glGetUniformLocation(prog, "bitmap_sampler");
-    dispatch->glUniform1i(sampler_uniform_location, 0);
+    glUseProgram(prog);
+    sampler_uniform_location = glGetUniformLocation(prog, "bitmap_sampler");
+    glUniform1i(sampler_uniform_location, 0);
 
     glamor_priv->put_image_xybitmap_fg_uniform_location =
-        dispatch->glGetUniformLocation(prog, "fg");
+        glGetUniformLocation(prog, "fg");
     glamor_priv->put_image_xybitmap_bg_uniform_location =
-        dispatch->glGetUniformLocation(prog, "bg");
+        glGetUniformLocation(prog, "bg");
     glamor_get_transform_uniform_locations(prog,
                                            &glamor_priv->
                                            put_image_xybitmap_transform);
     glamor_priv->put_image_xybitmap_prog = prog;
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
 #endif
 }
 
@@ -162,40 +161,38 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
     if (!glamor_set_planemask(pixmap, gc->planemask))
         goto fail;
 
-    dispatch->glUseProgram(glamor_priv->put_image_xybitmap_prog);
+    glUseProgram(glamor_priv->put_image_xybitmap_prog);
 
     glamor_get_color_4f_from_pixel(pixmap, gc->fgPixel, fg);
-    dispatch->glUniform4fv
-        (glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg);
+    glUniform4fv(glamor_priv->put_image_xybitmap_fg_uniform_location, 1, fg);
     glamor_get_color_4f_from_pixel(pixmap, gc->bgPixel, bg);
-    dispatch->glUniform4fv
-        (glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg);
-
-    dispatch->glGenTextures(1, &tex);
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glEnable(GL_TEXTURE_2D);
-    dispatch->glBindTexture(GL_TEXTURE_2D, tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8);
-    dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad);
-    dispatch->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
-                           w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits);
-    dispatch->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-    dispatch->glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+    glUniform4fv(glamor_priv->put_image_xybitmap_bg_uniform_location, 1, bg);
+
+    glGenTextures(1, &tex);
+    glActiveTexture(GL_TEXTURE0);
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8);
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, left_pad);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
+                 w, h, 0, GL_COLOR_INDEX, GL_BITMAP, bits);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
 
     /* Now that we've set up our bitmap texture and the shader, shove
      * the destination rectangle through the cliprects and run the
      * shader on the resulting fragments.
      */
-    dispatch->glVertexPointer(2, GL_FLOAT, 0, dest_coords);
-    dispatch->glEnableClientState(GL_VERTEX_ARRAY);
-    dispatch->glClientActiveTexture(GL_TEXTURE0);
-    dispatch->glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords);
-    dispatch->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    glVertexPointer(2, GL_FLOAT, 0, dest_coords);
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glClientActiveTexture(GL_TEXTURE0);
+    glTexCoordPointer(2, GL_FLOAT, 0, bitmap_coords);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 
-    dispatch->glEnable(GL_SCISSOR_TEST);
+    glEnable(GL_SCISSOR_TEST);
     clip = fbGetCompositeClip(gc);
     for (nbox = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nbox--; box++) {
         int x1 = x;
@@ -214,19 +211,18 @@ glamor_put_image_xybitmap(DrawablePtr drawable, GCPtr gc,
         if (x1 >= x2 || y1 >= y2)
             continue;
 
-        dispatch->glScissor(box->x1,
-                            y_flip(pixmap, box->y1),
-                            box->x2 - box->x1, box->y2 - box->y1);
-        dispatch->glDrawArrays(GL_QUADS, 0, 4);
+        glScissor(box->x1, y_flip(pixmap, box->y1),
+                  box->x2 - box->x1, box->y2 - box->y1);
+        glDrawArrays(GL_QUADS, 0, 4);
     }
 
-    dispatch->glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_SCISSOR_TEST);
     glamor_set_alu(GXcopy);
     glamor_set_planemask(pixmap, ~0);
-    dispatch->glDeleteTextures(1, &tex);
-    dispatch->glDisable(GL_TEXTURE_2D);
-    dispatch->glDisableClientState(GL_VERTEX_ARRAY);
-    dispatch->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glDeleteTextures(1, &tex);
+    glDisable(GL_TEXTURE_2D);
+    glDisableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     return;
     glamor_set_alu(GXcopy);
     glamor_set_planemask(pixmap, ~0);
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 4a3a97c..760af83 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -62,8 +62,7 @@ static struct blendinfo composite_op_info[] = {
 
 #define RepeatFix			10
 static GLuint
-glamor_create_composite_fs(glamor_gl_dispatch *dispatch,
-                           struct shader_key *key)
+glamor_create_composite_fs(struct shader_key *key)
 {
     const char *repeat_define =
         "#define RepeatNone               	      0\n"
@@ -266,15 +265,14 @@ glamor_create_composite_fs(glamor_gl_dispatch *dispatch,
     XNFasprintf(&source, "%s%s%s%s%s%s", repeat_define, relocate_texture,
                 rel_sampler, source_fetch, mask_fetch, in);
 
-    prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, source);
+    prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, source);
     free(source);
 
     return prog;
 }
 
 static GLuint
-glamor_create_composite_vs(glamor_gl_dispatch *dispatch,
-                           struct shader_key *key)
+glamor_create_composite_vs(struct shader_key *key)
 {
     const char *main_opening =
         "attribute vec4 v_position;\n"
@@ -304,7 +302,7 @@ glamor_create_composite_vs(glamor_gl_dispatch *dispatch,
                 main_opening,
                 source_coords_setup, mask_coords_setup, main_closing);
 
-    prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, source);
+    prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, source);
     free(source);
 
     return prog;
@@ -317,55 +315,52 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
     GLuint vs, fs, prog;
     GLint source_sampler_uniform_location, mask_sampler_uniform_location;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    vs = glamor_create_composite_vs(dispatch, key);
+    glamor_get_dispatch(glamor_priv);
+    vs = glamor_create_composite_vs(key);
     if (vs == 0)
         goto out;
-    fs = glamor_create_composite_fs(dispatch, key);
+    fs = glamor_create_composite_fs(key);
     if (fs == 0)
         goto out;
 
-    prog = dispatch->glCreateProgram();
-    dispatch->glAttachShader(prog, vs);
-    dispatch->glAttachShader(prog, fs);
+    prog = glCreateProgram();
+    glAttachShader(prog, vs);
+    glAttachShader(prog, fs);
 
-    dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position");
-    dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    dispatch->glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1");
+    glBindAttribLocation(prog, GLAMOR_VERTEX_POS, "v_position");
+    glBindAttribLocation(prog, GLAMOR_VERTEX_SOURCE, "v_texcoord0");
+    glBindAttribLocation(prog, GLAMOR_VERTEX_MASK, "v_texcoord1");
 
-    glamor_link_glsl_prog(dispatch, prog);
+    glamor_link_glsl_prog(prog);
 
     shader->prog = prog;
 
-    dispatch->glUseProgram(prog);
+    glUseProgram(prog);
 
     if (key->source == SHADER_SOURCE_SOLID) {
-        shader->source_uniform_location =
-            dispatch->glGetUniformLocation(prog, "source");
+        shader->source_uniform_location = glGetUniformLocation(prog, "source");
     }
     else {
         source_sampler_uniform_location =
-            dispatch->glGetUniformLocation(prog, "source_sampler");
-        dispatch->glUniform1i(source_sampler_uniform_location, 0);
-        shader->source_wh = dispatch->glGetUniformLocation(prog, "source_wh");
+            glGetUniformLocation(prog, "source_sampler");
+        glUniform1i(source_sampler_uniform_location, 0);
+        shader->source_wh = glGetUniformLocation(prog, "source_wh");
         shader->source_repeat_mode =
-            dispatch->glGetUniformLocation(prog, "source_repeat_mode");
+            glGetUniformLocation(prog, "source_repeat_mode");
     }
 
     if (key->mask != SHADER_MASK_NONE) {
         if (key->mask == SHADER_MASK_SOLID) {
-            shader->mask_uniform_location =
-                dispatch->glGetUniformLocation(prog, "mask");
+            shader->mask_uniform_location = glGetUniformLocation(prog, "mask");
         }
         else {
             mask_sampler_uniform_location =
-                dispatch->glGetUniformLocation(prog, "mask_sampler");
-            dispatch->glUniform1i(mask_sampler_uniform_location, 1);
-            shader->mask_wh = dispatch->glGetUniformLocation(prog, "mask_wh");
+                glGetUniformLocation(prog, "mask_sampler");
+            glUniform1i(mask_sampler_uniform_location, 1);
+            shader->mask_wh = glGetUniformLocation(prog, "mask_wh");
             shader->mask_repeat_mode =
-                dispatch->glGetUniformLocation(prog, "mask_repeat_mode");
+                glGetUniformLocation(prog, "mask_repeat_mode");
         }
     }
 
@@ -407,23 +402,21 @@ void
 glamor_init_composite_shaders(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     unsigned short *eb;
     float *vb = NULL;
     int eb_size;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glGenBuffers(1, &glamor_priv->vbo);
-    dispatch->glGenBuffers(1, &glamor_priv->ebo);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
+    glamor_get_dispatch(glamor_priv);
+    glGenBuffers(1, &glamor_priv->vbo);
+    glGenBuffers(1, &glamor_priv->ebo);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     eb_size = GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(short) * 2;
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER,
-                               eb_size, NULL, GL_STATIC_DRAW);
-        eb = dispatch->glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, NULL, GL_STATIC_DRAW);
+        eb = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
     }
     else {
         vb = malloc(GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) * 2);
@@ -438,19 +431,18 @@ glamor_init_composite_shaders(ScreenPtr screen)
     glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT);
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        dispatch->glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-        dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     }
     else {
-        dispatch->glBufferData(GL_ELEMENT_ARRAY_BUFFER,
-                               eb_size, eb, GL_STATIC_DRAW);
-        dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
-        dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        dispatch->glBufferData(GL_ARRAY_BUFFER,
-                               GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) *
-                               2, NULL, GL_DYNAMIC_DRAW);
-        dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
+        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+        glBufferData(GL_ARRAY_BUFFER,
+                     GLAMOR_COMPOSITE_VBO_VERT_CNT * sizeof(float) *
+                     2, NULL, GL_DYNAMIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
 
         free(eb);
         glamor_priv->vb = (char *) vb;
@@ -463,21 +455,20 @@ void
 glamor_fini_composite_shaders(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     glamor_composite_shader *shader;
     int i, j, k;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glDeleteBuffers(1, &glamor_priv->vbo);
-    dispatch->glDeleteBuffers(1, &glamor_priv->ebo);
+    glamor_get_dispatch(glamor_priv);
+    glDeleteBuffers(1, &glamor_priv->vbo);
+    glDeleteBuffers(1, &glamor_priv->ebo);
 
     for (i = 0; i < SHADER_SOURCE_COUNT; i++)
         for (j = 0; j < SHADER_MASK_COUNT; j++)
             for (k = 0; k < SHADER_IN_COUNT; k++) {
                 shader = &glamor_priv->composite_shader[i][j][k];
                 if (shader->prog)
-                    dispatch->glDeleteProgram(shader->prog);
+                    glDeleteProgram(shader->prog);
             }
     if (glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP && glamor_priv->vb)
         free(glamor_priv->vb);
@@ -535,44 +526,35 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
                              glamor_pixmap_private *pixmap_priv,
                              GLuint wh_location, GLuint repeat_location)
 {
-    glamor_gl_dispatch *dispatch;
     float wh[4];
     int repeat_type;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glActiveTexture(GL_TEXTURE0 + unit);
-    dispatch->glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
+    glamor_get_dispatch(glamor_priv);
+    glActiveTexture(GL_TEXTURE0 + unit);
+    glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
     repeat_type = picture->repeatType;
     switch (picture->repeatType) {
     case RepeatNone:
 #ifndef GLAMOR_GLES2
         /* XXX  GLES2 doesn't support GL_CLAMP_TO_BORDER. */
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
-                                  GL_CLAMP_TO_BORDER);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
-                                  GL_CLAMP_TO_BORDER);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
 #else
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
-                                  GL_CLAMP_TO_EDGE);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
-                                  GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 #endif
         break;
     case RepeatNormal:
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
         break;
     case RepeatPad:
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
-                                  GL_CLAMP_TO_EDGE);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
-                                  GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
         break;
     case RepeatReflect:
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
-                                  GL_MIRRORED_REPEAT);
-        dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
-                                  GL_MIRRORED_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
         break;
     }
 
@@ -580,22 +562,18 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
     default:
     case PictFilterFast:
     case PictFilterNearest:
-        dispatch->glTexParameteri(GL_TEXTURE_2D,
-                                  GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        dispatch->glTexParameteri(GL_TEXTURE_2D,
-                                  GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         break;
     case PictFilterGood:
     case PictFilterBest:
     case PictFilterBilinear:
-        dispatch->glTexParameteri(GL_TEXTURE_2D,
-                                  GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        dispatch->glTexParameteri(GL_TEXTURE_2D,
-                                  GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         break;
     }
 #ifndef GLAMOR_GLES2
-    dispatch->glEnable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_2D);
 #endif
 
     /*
@@ -615,19 +593,18 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
         if ((wh[0] != 1.0 || wh[1] != 1.0)
             || (glamor_priv->gl_flavor == GLAMOR_GL_ES2
                 && repeat_type == RepeatFix))
-            dispatch->glUniform4fv(wh_location, 1, wh);
+            glUniform4fv(wh_location, 1, wh);
         else
             repeat_type -= RepeatFix;
     }
-    dispatch->glUniform1i(repeat_location, repeat_type);
+    glUniform1i(repeat_location, repeat_type);
     glamor_put_dispatch(glamor_priv);
 }
 
 static void
-glamor_set_composite_solid(glamor_gl_dispatch *dispatch, float *color,
-                           GLint uniform_location)
+glamor_set_composite_solid(float *color, GLint uniform_location)
 {
-    dispatch->glUniform4fv(uniform_location, 1, color);
+    glUniform4fv(uniform_location, 1, color);
 }
 
 static int
@@ -729,7 +706,6 @@ void
 glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
     int vert_size;
 
     glamor_priv->render_nr_verts = 0;
@@ -741,63 +717,52 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 
     vert_size = n_verts * glamor_priv->vb_stride;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+    glamor_get_dispatch(glamor_priv);
+    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
             glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT *
                 glamor_priv->vb_stride;
             glamor_priv->vbo_offset = 0;
-            dispatch->glBufferData(GL_ARRAY_BUFFER,
-                                   glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
+            glBufferData(GL_ARRAY_BUFFER,
+                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
         }
 
-        glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER,
-                                                     glamor_priv->vbo_offset,
-                                                     vert_size,
-                                                     GL_MAP_WRITE_BIT |
-                                                     GL_MAP_UNSYNCHRONIZED_BIT);
+        glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
+                                           glamor_priv->vbo_offset,
+                                           vert_size,
+                                           GL_MAP_WRITE_BIT |
+                                           GL_MAP_UNSYNCHRONIZED_BIT);
         assert(glamor_priv->vb != NULL);
         glamor_priv->vb -= glamor_priv->vbo_offset;
     }
     else
         glamor_priv->vbo_offset = 0;
 
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long)
-                                              glamor_priv->vbo_offset));
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
+                          glamor_priv->vb_stride,
+                          (void *) ((long)
+                                    glamor_priv->vbo_offset));
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
     if (glamor_priv->has_source_coords) {
-        dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
-                                        GL_FLOAT, GL_FALSE,
-                                        glamor_priv->vb_stride, (void *) ((long)
-                                                                          glamor_priv->
-                                                                          vbo_offset
-                                                                          +
-                                                                          2 *
-                                                                          sizeof
-                                                                          (float)));
-        dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+        glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
+                              GL_FLOAT, GL_FALSE,
+                              glamor_priv->vb_stride,
+                              (void *) ((long) glamor_priv->vbo_offset +
+                                        2 * sizeof(float)));
+        glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     }
 
     if (glamor_priv->has_mask_coords) {
-        dispatch->glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2,
-                                        GL_FLOAT, GL_FALSE,
-                                        glamor_priv->vb_stride, (void *) ((long)
-                                                                          glamor_priv->
-                                                                          vbo_offset
-                                                                          +
-                                                                          (glamor_priv->
-                                                                           has_source_coords
-                                                                           ? 4 :
-                                                                           2) *
-                                                                          sizeof
-                                                                          (float)));
-        dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
+        glVertexAttribPointer(GLAMOR_VERTEX_MASK, 2, GL_FLOAT, GL_FALSE,
+                              glamor_priv->vb_stride,
+                              (void *) ((long) glamor_priv->vbo_offset +
+                                        (glamor_priv->has_source_coords ?
+                                         4 : 2) * sizeof(float)));
+        glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
     }
     glamor_put_dispatch(glamor_priv);
 }
@@ -831,30 +796,27 @@ static void
 glamor_flush_composite_rects(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        dispatch->glUnmapBuffer(GL_ARRAY_BUFFER);
+        glUnmapBuffer(GL_ARRAY_BUFFER);
     else {
 
-        dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        dispatch->glBufferData(GL_ARRAY_BUFFER,
-                               glamor_priv->vbo_offset,
-                               glamor_priv->vb, GL_DYNAMIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
+                     glamor_priv->vb, GL_DYNAMIC_DRAW);
     }
 
     if (!glamor_priv->render_nr_verts)
         return;
 
 #ifndef GLAMOR_GLES2
-    dispatch->glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts,
-                                  (glamor_priv->render_nr_verts * 3) / 2,
-                                  GL_UNSIGNED_SHORT, NULL);
+    glDrawRangeElements(GL_TRIANGLES, 0, glamor_priv->render_nr_verts,
+                        (glamor_priv->render_nr_verts * 3) / 2,
+                        GL_UNSIGNED_SHORT, NULL);
 #else
-    dispatch->glDrawElements(GL_TRIANGLES,
-                             (glamor_priv->render_nr_verts * 3) / 2,
-                             GL_UNSIGNED_SHORT, NULL);
+    glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
+                   GL_UNSIGNED_SHORT, NULL);
 #endif
     glamor_put_dispatch(glamor_priv);
 }
@@ -1228,17 +1190,15 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
                                   glamor_composite_shader *shader,
                                   struct blendinfo *op_info)
 {
-    glamor_gl_dispatch *dispatch;
     glamor_screen_private *glamor_priv;
 
     glamor_priv = dest_priv->base.glamor_priv;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glUseProgram(shader->prog);
+    glamor_get_dispatch(glamor_priv);
+    glUseProgram(shader->prog);
 
     if (key->source == SHADER_SOURCE_SOLID) {
-        glamor_set_composite_solid(dispatch,
-                                   shader->source_solid_color,
+        glamor_set_composite_solid(shader->source_solid_color,
                                    shader->source_uniform_location);
     }
     else {
@@ -1250,8 +1210,7 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
 
     if (key->mask != SHADER_MASK_NONE) {
         if (key->mask == SHADER_MASK_SOLID) {
-            glamor_set_composite_solid(dispatch,
-                                       shader->mask_solid_color,
+            glamor_set_composite_solid(shader->mask_solid_color,
                                        shader->mask_uniform_location);
         }
         else {
@@ -1263,11 +1222,11 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
     }
 
     if (op_info->source_blend == GL_ONE && op_info->dest_blend == GL_ZERO) {
-        dispatch->glDisable(GL_BLEND);
+        glDisable(GL_BLEND);
     }
     else {
-        dispatch->glEnable(GL_BLEND);
-        dispatch->glBlendFunc(op_info->source_blend, op_info->dest_blend);
+        glEnable(GL_BLEND);
+        glBlendFunc(op_info->source_blend, op_info->dest_blend);
     }
 
     glamor_put_dispatch(glamor_priv);
@@ -1289,7 +1248,6 @@ glamor_composite_with_shader(CARD8 op,
     PixmapPtr dest_pixmap = dest_pixmap_priv->base.pixmap;
     PixmapPtr source_pixmap = NULL;
     PixmapPtr mask_pixmap = NULL;
-    glamor_gl_dispatch *dispatch = NULL;
     GLfloat dst_xscale, dst_yscale;
     GLfloat mask_xscale = 1, mask_yscale = 1, src_xscale = 1, src_yscale = 1;
     struct shader_key key, key_ca;
@@ -1328,7 +1286,7 @@ glamor_composite_with_shader(CARD8 op,
     glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv);
     glamor_composite_set_shader_blend(dest_pixmap_priv, &key, shader, &op_info);
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID;
     glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
@@ -1445,20 +1403,20 @@ glamor_composite_with_shader(CARD8 op,
         }
     }
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
-    dispatch->glDisable(GL_BLEND);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
+    glDisable(GL_BLEND);
 #ifndef GLAMOR_GLES2
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glDisable(GL_TEXTURE_2D);
-    dispatch->glActiveTexture(GL_TEXTURE1);
-    dispatch->glDisable(GL_TEXTURE_2D);
+    glActiveTexture(GL_TEXTURE0);
+    glDisable(GL_TEXTURE_2D);
+    glActiveTexture(GL_TEXTURE1);
+    glDisable(GL_TEXTURE_2D);
 #endif
     DEBUGF("finish rendering.\n");
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
     if (saved_source_format)
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index 9c8e521..8ceb549 100644
--- a/glamor/glamor_tile.c
+++ b/glamor/glamor_tile.c
@@ -37,7 +37,6 @@ void
 glamor_init_tile_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     const char *tile_vs =
         "attribute vec4 v_position;\n"
         "attribute vec4 v_texcoord0;\n"
@@ -63,27 +62,27 @@ glamor_init_tile_shader(ScreenPtr screen)
     GLint sampler_uniform_location;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    glamor_priv->tile_prog = dispatch->glCreateProgram();
-    vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, tile_vs);
-    fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, tile_fs);
-    dispatch->glAttachShader(glamor_priv->tile_prog, vs_prog);
-    dispatch->glAttachShader(glamor_priv->tile_prog, fs_prog);
-
-    dispatch->glBindAttribLocation(glamor_priv->tile_prog,
-                                   GLAMOR_VERTEX_POS, "v_position");
-    dispatch->glBindAttribLocation(glamor_priv->tile_prog,
-                                   GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(dispatch, glamor_priv->tile_prog);
+    glamor_get_dispatch(glamor_priv);
+    glamor_priv->tile_prog = glCreateProgram();
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, tile_vs);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, tile_fs);
+    glAttachShader(glamor_priv->tile_prog, vs_prog);
+    glAttachShader(glamor_priv->tile_prog, fs_prog);
+
+    glBindAttribLocation(glamor_priv->tile_prog,
+                         GLAMOR_VERTEX_POS, "v_position");
+    glBindAttribLocation(glamor_priv->tile_prog,
+                         GLAMOR_VERTEX_SOURCE, "v_texcoord0");
+    glamor_link_glsl_prog(glamor_priv->tile_prog);
 
     sampler_uniform_location =
-        dispatch->glGetUniformLocation(glamor_priv->tile_prog, "sampler");
-    dispatch->glUseProgram(glamor_priv->tile_prog);
-    dispatch->glUniform1i(sampler_uniform_location, 0);
+        glGetUniformLocation(glamor_priv->tile_prog, "sampler");
+    glUseProgram(glamor_priv->tile_prog);
+    glUniform1i(sampler_uniform_location, 0);
 
     glamor_priv->tile_wh =
-        dispatch->glGetUniformLocation(glamor_priv->tile_prog, "wh");
-    dispatch->glUseProgram(0);
+        glGetUniformLocation(glamor_priv->tile_prog, "wh");
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -91,11 +90,10 @@ void
 glamor_fini_tile_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glDeleteProgram(glamor_priv->tile_prog);
+    glamor_get_dispatch(glamor_priv);
+    glDeleteProgram(glamor_priv->tile_prog);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -105,7 +103,6 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
 {
     ScreenPtr screen = pixmap->drawable.pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
     int x1 = x;
     int x2 = x + width;
     int y1 = y;
@@ -127,19 +124,19 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
     pixmap_priv_get_dest_scale(dst_pixmap_priv, &dst_xscale, &dst_yscale);
     pixmap_priv_get_scale(src_pixmap_priv, &src_xscale, &src_yscale);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glUseProgram(glamor_priv->tile_prog);
+    glamor_get_dispatch(glamor_priv);
+    glUseProgram(glamor_priv->tile_prog);
 
     glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
-    dispatch->glUniform2fv(glamor_priv->tile_wh, 1, wh);
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glUniform2fv(glamor_priv->tile_wh, 1, wh);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 #ifndef GLAMOR_GLES2
-    dispatch->glEnable(GL_TEXTURE_2D);
+    glEnable(GL_TEXTURE_2D);
 #endif
     glamor_set_repeat_normalize_tcoords
         (src_pixmap_priv, RepeatNormal,
@@ -147,26 +144,25 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
          tile_x1, tile_y1,
          tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
-                                    GL_FLOAT, GL_FALSE,
-                                    2 * sizeof(float), source_texcoords);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), source_texcoords);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
     glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale,
                                  x1, y1,
                                  x2, y2, glamor_priv->yInverted, vertices);
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), vertices);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), vertices);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 #ifndef GLAMOR_GLES2
-    dispatch->glDisable(GL_TEXTURE_2D);
+    glDisable(GL_TEXTURE_2D);
 #endif
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glUseProgram(0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
 
     glamor_priv->state = RENDER_STATE;
@@ -182,7 +178,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     glamor_pixmap_private *dst_pixmap_priv;
     glamor_pixmap_private *src_pixmap_priv;
-    glamor_gl_dispatch *dispatch;
 
     dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
     src_pixmap_priv = glamor_get_pixmap_private(tile);
@@ -206,8 +201,8 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
         goto fail;
     }
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-    if (!glamor_set_alu(dispatch, alu)) {
+    glamor_get_dispatch(glamor_priv);
+    if (!glamor_set_alu(alu)) {
         glamor_fallback("unsupported alu %x\n", alu);
         glamor_put_dispatch(glamor_priv);
         goto fail;
@@ -302,7 +297,7 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
     else
         _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
 
-    glamor_set_alu(dispatch, GXcopy);
+    glamor_set_alu(GXcopy);
     glamor_put_dispatch(glamor_priv);
     return TRUE;
  fail:
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index cd99a47..b398213 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -204,23 +204,21 @@ static void
 glamor_flush_composite_triangles(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        dispatch->glUnmapBuffer(GL_ARRAY_BUFFER);
+        glUnmapBuffer(GL_ARRAY_BUFFER);
     else {
 
-        dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-        dispatch->glBufferData(GL_ARRAY_BUFFER,
-                               glamor_priv->vbo_offset,
-                               glamor_priv->vb, GL_DYNAMIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+        glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
+                     glamor_priv->vb, GL_DYNAMIC_DRAW);
     }
 
     if (!glamor_priv->render_nr_verts)
         return;
 
-    dispatch->glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts);
+    glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -582,7 +580,6 @@ static void
 glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_gl_dispatch *dispatch;
     int stride;
     int vert_size;
 
@@ -605,25 +602,25 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
 
     vert_size = n_verts * glamor_priv->vb_stride;
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+    glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
         if (glamor_priv->vbo_size < (glamor_priv->vbo_offset + vert_size)) {
             glamor_priv->vbo_size = GLAMOR_COMPOSITE_VBO_VERT_CNT *
                 glamor_priv->vb_stride;
             glamor_priv->vbo_offset = 0;
-            dispatch->glBufferData(GL_ARRAY_BUFFER,
-                                   glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
+            glBufferData(GL_ARRAY_BUFFER,
+                         glamor_priv->vbo_size, NULL, GL_STREAM_DRAW);
         }
 
-        glamor_priv->vb = dispatch->glMapBufferRange(GL_ARRAY_BUFFER,
+        glamor_priv->vb = glMapBufferRange(GL_ARRAY_BUFFER,
                                                      glamor_priv->vbo_offset,
                                                      vert_size,
                                                      GL_MAP_WRITE_BIT |
@@ -636,41 +633,41 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
         glamor_priv->vbo_offset = 0;
     }
 
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
     /* Set the vertex pointer. */
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset));
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, glamor_priv->vb_stride,
+                          (void *) ((long) glamor_priv->vbo_offset));
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     stride = 2;
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
-                                    GL_FALSE, glamor_priv->vb_stride,
-                                    (void *) ((long) glamor_priv->vbo_offset +
-                                              stride * sizeof(float)));
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
+                          GL_FALSE, glamor_priv->vb_stride,
+                          (void *) ((long) glamor_priv->vbo_offset +
+                                    stride * sizeof(float)));
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     stride += 2;
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT,
+    glVertexAttribPointer(GLAMOR_VERTEX_TOP_BOTTOM, 2, GL_FLOAT,
                                     GL_FALSE, glamor_priv->vb_stride,
                                     (void *) ((long) glamor_priv->vbo_offset +
                                               stride * sizeof(float)));
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
     stride += 2;
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT,
+    glVertexAttribPointer(GLAMOR_VERTEX_LEFT_PARAM, 4, GL_FLOAT,
                                     GL_FALSE, glamor_priv->vb_stride,
                                     (void *) ((long) glamor_priv->vbo_offset +
                                               stride * sizeof(float)));
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
     stride += 4;
 
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT,
+    glVertexAttribPointer(GLAMOR_VERTEX_RIGHT_PARAM, 4, GL_FLOAT,
                                     GL_FALSE, glamor_priv->vb_stride,
                                     (void *) ((long) glamor_priv->vbo_offset +
                                               stride * sizeof(float)));
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
     glamor_put_dispatch(glamor_priv);
 }
@@ -701,7 +698,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     GLfloat dst_xscale, dst_yscale;
     BoxRec bounds;
     PicturePtr temp_src = src;
-    glamor_gl_dispatch *dispatch = NULL;
     int vert_stride = 3;
     int ntriangle_per_loop;
     int nclip_rect;
@@ -815,6 +811,8 @@ _glamor_trapezoids_with_shader(CARD8 op,
         goto TRAPEZOID_OUT;
     }
 
+    glamor_get_dispatch(glamor_priv);
+
     box = REGION_RECTS(&region);
     nbox = REGION_NUM_RECTS(&region);
     pbox = box;
@@ -833,8 +831,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
                                     key.mask != SHADER_MASK_SOLID);
 
-    dispatch = glamor_get_dispatch(glamor_priv);
-
     glamor_get_drawable_deltas(dst->pDrawable, dest_pixmap,
                                &dest_x_off, &dest_y_off);
 
@@ -974,19 +970,20 @@ _glamor_trapezoids_with_shader(CARD8 op,
     ret = TRUE;
 
  TRAPEZOID_RESET_GL:
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
-    dispatch->glDisable(GL_BLEND);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
+    glDisable(GL_BLEND);
 #ifndef GLAMOR_GLES2
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glDisable(GL_TEXTURE_2D);
-    dispatch->glActiveTexture(GL_TEXTURE1);
-    dispatch->glDisable(GL_TEXTURE_2D);
+    glActiveTexture(GL_TEXTURE0);
+    glDisable(GL_TEXTURE_2D);
+    glActiveTexture(GL_TEXTURE1);
+    glDisable(GL_TEXTURE_2D);
 #endif
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
+    glamor_put_dispatch(glamor_priv);
 
  TRAPEZOID_OUT:
     if (box) {
@@ -1002,10 +999,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
         }
     }
 
-    if (dispatch) {
-        glamor_put_dispatch(glamor_priv);
-    }
-
     return ret;
 }
 
@@ -1013,7 +1006,6 @@ void
 glamor_init_trapezoid_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     GLint fs_prog, vs_prog;
 
     const char *trapezoid_vs =
@@ -1344,32 +1336,30 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
         "}\n";
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
-    glamor_priv->trapezoid_prog = dispatch->glCreateProgram();
+    glamor_priv->trapezoid_prog = glCreateProgram();
 
-    vs_prog = glamor_compile_glsl_prog(dispatch,
-                                       GL_VERTEX_SHADER, trapezoid_vs);
-    fs_prog = glamor_compile_glsl_prog(dispatch,
-                                       GL_FRAGMENT_SHADER, trapezoid_fs);
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, trapezoid_vs);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, trapezoid_fs);
 
-    dispatch->glAttachShader(glamor_priv->trapezoid_prog, vs_prog);
-    dispatch->glAttachShader(glamor_priv->trapezoid_prog, fs_prog);
+    glAttachShader(glamor_priv->trapezoid_prog, vs_prog);
+    glAttachShader(glamor_priv->trapezoid_prog, fs_prog);
 
-    dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog,
-                                   GLAMOR_VERTEX_POS, "v_positionsition");
-    dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog,
-                                   GLAMOR_VERTEX_SOURCE, "v_texcoord");
-    dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog,
-                                   GLAMOR_VERTEX_TOP_BOTTOM, "v_top_bottom");
-    dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog,
-                                   GLAMOR_VERTEX_LEFT_PARAM, "v_left_param");
-    dispatch->glBindAttribLocation(glamor_priv->trapezoid_prog,
-                                   GLAMOR_VERTEX_RIGHT_PARAM, "v_right_param");
+    glBindAttribLocation(glamor_priv->trapezoid_prog,
+                         GLAMOR_VERTEX_POS, "v_positionsition");
+    glBindAttribLocation(glamor_priv->trapezoid_prog,
+                         GLAMOR_VERTEX_SOURCE, "v_texcoord");
+    glBindAttribLocation(glamor_priv->trapezoid_prog,
+                         GLAMOR_VERTEX_TOP_BOTTOM, "v_top_bottom");
+    glBindAttribLocation(glamor_priv->trapezoid_prog,
+                         GLAMOR_VERTEX_LEFT_PARAM, "v_left_param");
+    glBindAttribLocation(glamor_priv->trapezoid_prog,
+                         GLAMOR_VERTEX_RIGHT_PARAM, "v_right_param");
 
-    glamor_link_glsl_prog(dispatch, glamor_priv->trapezoid_prog);
+    glamor_link_glsl_prog(glamor_priv->trapezoid_prog);
 
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
 
     glamor_put_dispatch(glamor_priv);
 }
@@ -1378,11 +1368,10 @@ void
 glamor_fini_trapezoid_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glDeleteProgram(glamor_priv->trapezoid_prog);
+    glamor_get_dispatch(glamor_priv);
+    glDeleteProgram(glamor_priv->trapezoid_prog);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -1392,7 +1381,6 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
                                        BoxRec *bounds)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     glamor_pixmap_private *pixmap_priv;
     PixmapPtr pixmap = NULL;
     GLint trapezoid_prog;
@@ -1425,20 +1413,20 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
         return FALSE;
     }
 
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
     pixmap_priv_get_dest_scale(pixmap_priv, (&xscale), (&yscale));
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
     /* Now draw the Trapezoid mask. */
-    dispatch->glUseProgram(trapezoid_prog);
+    glUseProgram(trapezoid_prog);
 
-    dispatch->glEnable(GL_BLEND);
-    dispatch->glBlendFunc(GL_ONE, GL_ONE);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE);
 
     nrect_max = GLAMOR_COMPOSITE_VBO_VERT_CNT / (4 * GLAMOR_VERTEX_RIGHT_PARAM);
 
@@ -1565,36 +1553,35 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
             continue;
 
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-            dispatch->glUnmapBuffer(GL_ARRAY_BUFFER);
+            glUnmapBuffer(GL_ARRAY_BUFFER);
         else {
-            dispatch->glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
-            dispatch->glBufferData(GL_ARRAY_BUFFER,
-                                   glamor_priv->vbo_offset,
-                                   glamor_priv->vb, GL_DYNAMIC_DRAW);
+            glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
+            glBufferData(GL_ARRAY_BUFFER, glamor_priv->vbo_offset,
+                         glamor_priv->vb, GL_DYNAMIC_DRAW);
         }
 
 #ifndef GLAMOR_GLES2
-        dispatch->glDrawRangeElements(GL_TRIANGLES, 0,
-                                      glamor_priv->render_nr_verts,
-                                      (glamor_priv->render_nr_verts * 3) / 2,
-                                      GL_UNSIGNED_SHORT, NULL);
+        glDrawRangeElements(GL_TRIANGLES, 0,
+                            glamor_priv->render_nr_verts,
+                            (glamor_priv->render_nr_verts * 3) / 2,
+                            GL_UNSIGNED_SHORT, NULL);
 #else
-        dispatch->glDrawElements(GL_TRIANGLES,
-                                 (glamor_priv->render_nr_verts * 3) / 2,
-                                 GL_UNSIGNED_SHORT, NULL);
+        glDrawElements(GL_TRIANGLES,
+                       (glamor_priv->render_nr_verts * 3) / 2,
+                       GL_UNSIGNED_SHORT, NULL);
 #endif
     }
 
-    dispatch->glBindBuffer(GL_ARRAY_BUFFER, 0);
-    dispatch->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-    dispatch->glBlendFunc(GL_ONE, GL_ZERO);
-    dispatch->glDisable(GL_BLEND);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
-    dispatch->glUseProgram(0);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    glBlendFunc(GL_ONE, GL_ZERO);
+    glDisable(GL_BLEND);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_TOP_BOTTOM);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_LEFT_PARAM);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
     return TRUE;
 }
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index ea827df..d427360 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1828,13 +1828,11 @@ glamor_restore_current(ScreenPtr screen)
     glamor_egl_restore_context(screen);
 }
 
-static inline glamor_gl_dispatch *
+static inline void
 glamor_get_dispatch(glamor_screen_private * glamor_priv)
 {
     if (glamor_priv->flags & GLAMOR_USE_EGL_SCREEN)
         glamor_make_current(glamor_priv->screen);
-
-    return &glamor_priv->_dispatch;
 }
 
 static inline void
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index cbe07c8..89787a4 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -90,23 +90,22 @@ void
 glamor_init_xv_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
     GLint fs_prog, vs_prog;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
-    glamor_priv->xv_prog = dispatch->glCreateProgram();
+    glamor_get_dispatch(glamor_priv);
+    glamor_priv->xv_prog = glCreateProgram();
 
-    vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, xv_vs);
-    fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, xv_ps);
-    dispatch->glAttachShader(glamor_priv->xv_prog, vs_prog);
-    dispatch->glAttachShader(glamor_priv->xv_prog, fs_prog);
+    vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xv_vs);
+    fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, xv_ps);
+    glAttachShader(glamor_priv->xv_prog, vs_prog);
+    glAttachShader(glamor_priv->xv_prog, fs_prog);
 
-    dispatch->glBindAttribLocation(glamor_priv->xv_prog,
-                                   GLAMOR_VERTEX_POS, "v_position");
-    dispatch->glBindAttribLocation(glamor_priv->xv_prog,
-                                   GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(dispatch, glamor_priv->xv_prog);
+    glBindAttribLocation(glamor_priv->xv_prog,
+                         GLAMOR_VERTEX_POS, "v_position");
+    glBindAttribLocation(glamor_priv->xv_prog,
+                         GLAMOR_VERTEX_SOURCE, "v_texcoord0");
+    glamor_link_glsl_prog(glamor_priv->xv_prog);
 
     glamor_put_dispatch(glamor_priv);
 }
@@ -115,12 +114,11 @@ void
 glamor_fini_xv_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
-    glamor_gl_dispatch *dispatch;
 
     glamor_priv = glamor_get_screen_private(screen);
-    dispatch = glamor_get_dispatch(glamor_priv);
+    glamor_get_dispatch(glamor_priv);
 
-    dispatch->glDeleteProgram(glamor_priv->xv_prog);
+    glDeleteProgram(glamor_priv->xv_prog);
     glamor_put_dispatch(glamor_priv);
 }
 
@@ -278,7 +276,6 @@ glamor_display_textured_video(glamor_port_private *port_priv)
     glamor_pixmap_private *pixmap_priv =
         glamor_get_pixmap_private(port_priv->pPixmap);
     glamor_pixmap_private *src_pixmap_priv[3];
-    glamor_gl_dispatch *dispatch;
     float vertices[32], texcoords[8];
     BoxPtr box = REGION_RECTS(&port_priv->clip);
     int nBox = REGION_NUM_RECTS(&port_priv->clip);
@@ -327,62 +324,53 @@ glamor_display_textured_video(glamor_port_private *port_priv)
                                   &src_yscale[i]);
         }
     }
-    dispatch = glamor_get_dispatch(glamor_priv);
-    dispatch->glUseProgram(glamor_priv->xv_prog);
-
-    uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "offsetyco");
-    dispatch->glUniform4f(uloc, off[0], off[1], off[2], yco);
-    uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "ucogamma");
-    dispatch->glUniform4f(uloc, uco[0], uco[1], uco[2], gamma);
-    uloc = dispatch->glGetUniformLocation(glamor_priv->xv_prog, "vco");
-    dispatch->glUniform4f(uloc, vco[0], vco[1], vco[2], 0);
-
-    dispatch->glActiveTexture(GL_TEXTURE0);
-    dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->base.fbo->tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    dispatch->glActiveTexture(GL_TEXTURE1);
-    dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->base.fbo->tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    dispatch->glActiveTexture(GL_TEXTURE2);
-    dispatch->glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->base.fbo->tex);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    dispatch->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    dispatch->glTexParameteri(GL_TEXTURE_2D,
-                              GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    sampler_loc =
-        dispatch->glGetUniformLocation(glamor_priv->xv_prog, "y_sampler");
-    dispatch->glUniform1i(sampler_loc, 0);
-    sampler_loc =
-        dispatch->glGetUniformLocation(glamor_priv->xv_prog, "u_sampler");
-    dispatch->glUniform1i(sampler_loc, 1);
-    sampler_loc =
-        dispatch->glGetUniformLocation(glamor_priv->xv_prog, "v_sampler");
-    dispatch->glUniform1i(sampler_loc, 2);
-
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
-                                    GL_FLOAT, GL_FALSE,
-                                    2 * sizeof(float), texcoords);
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-
-    dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                                    GL_FALSE, 2 * sizeof(float), vertices);
-
-    dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glamor_get_dispatch(glamor_priv);
+    glUseProgram(glamor_priv->xv_prog);
+
+    uloc = glGetUniformLocation(glamor_priv->xv_prog, "offsetyco");
+    glUniform4f(uloc, off[0], off[1], off[2], yco);
+    uloc = glGetUniformLocation(glamor_priv->xv_prog, "ucogamma");
+    glUniform4f(uloc, uco[0], uco[1], uco[2], gamma);
+    uloc = glGetUniformLocation(glamor_priv->xv_prog, "vco");
+    glUniform4f(uloc, vco[0], vco[1], vco[2], 0);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[0]->base.fbo->tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[1]->base.fbo->tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glActiveTexture(GL_TEXTURE2);
+    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv[2]->base.fbo->tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "y_sampler");
+    glUniform1i(sampler_loc, 0);
+    sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "u_sampler");
+    glUniform1i(sampler_loc, 1);
+    sampler_loc = glGetUniformLocation(glamor_priv->xv_prog, "v_sampler");
+    glUniform1i(sampler_loc, 2);
+
+    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2,
+                          GL_FLOAT, GL_FALSE,
+                          2 * sizeof(float), texcoords);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                          GL_FALSE, 2 * sizeof(float), vertices);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     for (i = 0; i < nBox; i++) {
         float off_x = box[i].x1 - port_priv->drw_x;
         float off_y = box[i].y1 - port_priv->drw_y;
@@ -418,13 +406,13 @@ glamor_display_textured_video(glamor_port_private *port_priv)
                                      srcy + srch,
                                      glamor_priv->yInverted, texcoords);
 
-        dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
 
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    dispatch->glUseProgram(0);
+    glUseProgram(0);
     glamor_put_dispatch(glamor_priv);
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
commit ddeca927498c9df3b5e62c7bf05e31e2a3aeaa52
Author: Mark Kettenis <kettenis at openbsd.org>
Date:   Sun Dec 15 14:31:10 2013 +0100

    sync: Avoid ridiculously long timeouts
    
    On OpenBSD, passing a timeout longer than 100000000 seconds to select(2) will
    make it fail with EINVAL.  As this is original 4.4BSD behaviour it is not
    inconceivable that other systems suffer from the same problem.  And Linux,
    though not suffering from any 4.4BSD heritage, briefly did something similar:
    
    <https://lkml.org/lkml/2012/8/31/263>
    
    So avoid calling AdjustWaitForDelay() instead of setting the timeout to
    (effectively) ULONG_MAX milliseconds.
    
    Signed-off-by: Mark Kettenis <kettenis at openbsd.org>
    Reviewed-by: Matthieu Herrb <matthieu at herrb.eu>

diff --git a/Xext/sync.c b/Xext/sync.c
index 97c9d51..755ed94 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -2731,27 +2731,24 @@ IdleTimeBlockHandler(void *pCounter, struct timeval **wt, void *LastSelectMask)
          * If we've been idle more than it, and someone wants to know about
          * that level-triggered, schedule an immediate wakeup.
          */
-        unsigned long timeout = -1;
 
         if (XSyncValueLessThan(idle, *greater)) {
             XSyncValue value;
             Bool overflow;
 
             XSyncValueSubtract(&value, *greater, idle, &overflow);
-            timeout = min(timeout, XSyncValueLow32(value));
+            AdjustWaitForDelay(wt, XSyncValueLow32(value));
         }
         else {
             for (list = counter->sync.pTriglist; list;
                  list = list->next) {
                 trig = list->pTrigger;
                 if (trig->CheckTrigger(trig, old_idle)) {
-                    timeout = min(timeout, 0);
+                    AdjustWaitForDelay(wt, 0);
                     break;
                 }
             }
         }
-
-        AdjustWaitForDelay(wt, timeout);
     }
 
     counter->value = old_idle;  /* pop */


More information about the Xquartz-changes mailing list