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

Jeremy Huddleston jeremyhu at freedesktop.org
Sat May 31 13:35:40 PDT 2014


 Xext/xres.c                                  |    4 
 Xext/xselinux_hooks.c                        |    4 
 Xi/exevents.c                                |   16 
 composite/compwindow.c                       |    1 
 config/config.c                              |    6 
 config/dbus-core.c                           |    4 
 configure.ac                                 |    1 
 dix/devices.c                                |    5 
 dix/dixutils.c                               |   25 
 dix/events.c                                 |    6 
 fb/fbpict.c                                  |    2 
 glamor/Makefile.am                           |    3 
 glamor/glamor.c                              |   25 
 glamor/glamor.h                              |    3 
 glamor/glamor_context.h                      |    9 
 glamor/glamor_copyarea.c                     |   18 
 glamor/glamor_core.c                         |   11 
 glamor/glamor_egl.c                          |   61 -
 glamor/glamor_fbo.c                          |   33 
 glamor/glamor_fill.c                         |   13 
 glamor/glamor_font.c                         |    7 
 glamor/glamor_getimage.c                     |   96 -
 glamor/glamor_glx.c                          |   26 
 glamor/glamor_glyphblt.c                     |   10 
 glamor/glamor_glyphs.c                       |    3 
 glamor/glamor_gradient.c                     |   24 
 glamor/glamor_image.c                        |  180 +++
 glamor/glamor_pixmap.c                       |   22 
 glamor/glamor_points.c                       |    5 
 glamor/glamor_priv.h                         |   31 
 glamor/glamor_putimage.c                     |  161 --
 glamor/glamor_rects.c                        |    4 
 glamor/glamor_render.c                       |   64 -
 glamor/glamor_segment.c                      |   11 
 glamor/glamor_spans.c                        |   10 
 glamor/glamor_text.c                         |   46 
 glamor/glamor_tile.c                         |   13 
 glamor/glamor_transfer.c                     |    6 
 glamor/glamor_trapezoid.c                    |   20 
 glamor/glamor_utils.h                        |   13 
 glamor/glamor_vbo.c                          |   17 
 glamor/glamor_xv.c                           |    7 
 glx/glxcmds.c                                |   22 
 glx/glxdri2.c                                |  124 +-
 glx/glxdriswrast.c                           |   10 
 glx/glxext.c                                 |   48 
 glx/glxserver.h                              |    1 
 hw/dmx/config/xdmxconfig.c                   |    3 
 hw/dmx/dmxfont.c                             |    2 
 hw/dmx/glxProxy/glxcmds.c                    |    2 
 hw/xfree86/common/compiler.h                 |    7 
 hw/xfree86/common/xf86Bus.c                  |    4 
 hw/xfree86/common/xf86Config.c               |   34 
 hw/xfree86/common/xf86Module.h               |    2 
 hw/xfree86/common/xf86Xinput.c               |    9 
 hw/xfree86/common/xf86platformBus.c          |    3 
 hw/xfree86/dri2/dri2.c                       |    6 
 hw/xfree86/int10/stub.c                      |    2 
 hw/xfree86/int10/xf86x86emu.c                |    1 
 hw/xfree86/man/xorg.conf.man                 |   24 
 hw/xfree86/modes/xf86Crtc.h                  |    8 
 hw/xfree86/modes/xf86Cursors.c               |   56 
 hw/xfree86/modes/xf86RandR12.c               |    7 
 hw/xfree86/os-support/linux/lnx_platform.c   |    2 
 hw/xfree86/os-support/linux/lnx_video.c      |    3 
 hw/xfree86/os-support/linux/systemd-logind.c |    7 
 hw/xfree86/parser/Device.c                   |    6 
 hw/xfree86/parser/Layout.c                   |    6 
 hw/xfree86/parser/Screen.c                   |    6 
 hw/xfree86/parser/xf86Parser.h               |    3 
 hw/xfree86/parser/xf86tokens.h               |    1 
 hw/xfree86/ramdac/IBM.c                      |    4 
 hw/xfree86/ramdac/TI.c                       |    2 
 hw/xfree86/ramdac/xf86Cursor.h               |   36 
 hw/xfree86/ramdac/xf86HWCurs.c               |   14 
 hw/xfree86/shadowfb/shadow.c                 | 1592 +--------------------------
 include/dix.h                                |    2 
 include/opaque.h                             |    1 
 include/servermd.h                           |   13 
 include/systemd-logind.h                     |    4 
 mi/miwindow.c                                |    2 
 os/busfault.c                                |    1 
 os/utils.c                                   |    9 
 randr/rrcrtc.c                               |    7 
 render/render.c                              |    2 
 xfixes/region.c                              |    6 
 86 files changed, 873 insertions(+), 2257 deletions(-)

New commits:
commit db2e708f31a162c6c66643d3559dd5f3e21ee06b
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Sep 27 17:44:42 2012 -0400

    glx: Require at least one True/DirectColor visual
    
    Mesa no longer supports rendering to anything less.  GLX 1.2 requires
    that the server advertise at least one GLX visual.  GLX 1.3 and 1.4 are
    more subtle: they require at least one fbconfig capable of window
    rendering, and _also_ require that window-capable fbconfigs have a
    non-zero value for the GLX_VISUAL_ID.  In either case we should refuse
    to init GLX if there's not at least one GL-capable visual on at least
    one screen.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glx/glxext.c b/glx/glxext.c
index c0142fe..c2de3ce 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -316,6 +316,23 @@ GlxPushProvider(__GLXprovider * provider)
     __glXProviderStack = provider;
 }
 
+static Bool
+checkScreenVisuals(void)
+{
+    int i, j;
+
+    for (i = 0; i < screenInfo.numScreens; i++) {
+        ScreenPtr screen = screenInfo.screens[i];
+        for (j = 0; j < screen->numVisuals; j++) {
+            if (screen->visuals[j].class == TrueColor ||
+                screen->visuals[j].class == DirectColor)
+                return True;
+        }
+    }
+
+    return False;
+}
+
 /*
 ** Initialize the GLX extension.
 */
@@ -334,6 +351,10 @@ GlxExtensionInit(void)
         *stack = &__glXDRISWRastProvider;
     }
 
+    /* Mesa requires at least one True/DirectColor visual */
+    if (!checkScreenVisuals())
+        return;
+
     __glXContextRes = CreateNewResourceType((DeleteType) ContextGone,
                                             "GLXContext");
     __glXDrawableRes = CreateNewResourceType((DeleteType) DrawableGone,
commit 6d684f916b4c33327d32ef1f48803bf90357287f
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed May 21 09:23:19 2014 -0400

    shadowfb: Fix initialization
    
    This has to run at initial CreateWindow time, at CreateScreenResources
    the root window doesn't actually exist yet.
    
    Tested-by: Michael Thayer <michael.thayer at oracle.com>
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Michael Thayer <michael.thayer at oracle.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/shadowfb/shadow.c b/hw/xfree86/shadowfb/shadow.c
index 10f72cc..d2481ed 100644
--- a/hw/xfree86/shadowfb/shadow.c
+++ b/hw/xfree86/shadowfb/shadow.c
@@ -29,14 +29,14 @@
 #include "picturestr.h"
 
 static Bool ShadowCloseScreen(ScreenPtr pScreen);
-static Bool ShadowCreateScreenResources(ScreenPtr pScreen);
+static Bool ShadowCreateRootWindow(WindowPtr pWin);
 
 typedef struct {
     ScrnInfoPtr pScrn;
     RefreshAreaFuncPtr preRefresh;
     RefreshAreaFuncPtr postRefresh;
     CloseScreenProcPtr CloseScreen;
-    CreateScreenResourcesProcPtr CreateScreenResources;
+    CreateWindowProcPtr CreateWindow;
 } ShadowScreenRec, *ShadowScreenPtr;
 
 static DevPrivateKeyRec ShadowScreenKeyRec;
@@ -71,10 +71,10 @@ ShadowFBInit2(ScreenPtr pScreen,
     pPriv->postRefresh = postRefreshArea;
 
     pPriv->CloseScreen = pScreen->CloseScreen;
-    pPriv->CreateScreenResources = pScreen->CreateScreenResources;
+    pPriv->CreateWindow = pScreen->CreateWindow;
 
     pScreen->CloseScreen = ShadowCloseScreen;
-    pScreen->CreateScreenResources = ShadowCreateScreenResources;
+    pScreen->CreateWindow = ShadowCreateRootWindow;
 
     return TRUE;
 }
@@ -117,16 +117,21 @@ shadowfbReportPost(DamagePtr damage, RegionPtr reg, void *closure)
 }
 
 static Bool
-ShadowCreateScreenResources(ScreenPtr pScreen)
+ShadowCreateRootWindow(WindowPtr pWin)
 {
     Bool ret;
-    WindowPtr pWin = pScreen->root;
+    ScreenPtr pScreen = pWin->drawable.pScreen;
     ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 
-    pScreen->CreateScreenResources = pPriv->CreateScreenResources;
-    ret = pScreen->CreateScreenResources(pScreen);
-    pPriv->CreateScreenResources = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = ShadowCreateScreenResources;
+    /* paranoia */
+    if (pWin != pScreen->root)
+        ErrorF("ShadowCreateRootWindow called unexpectedly\n");
+
+    /* call down, but don't hook ourselves back in; we know the first time
+     * we're called it's for the root window.
+     */
+    pScreen->CreateWindow = pPriv->CreateWindow;
+    ret = pScreen->CreateWindow(pWin);
 
     /* this might look like it leaks, but the damage code reaps listeners
      * when their drawable disappears.
@@ -159,7 +164,6 @@ ShadowCloseScreen(ScreenPtr pScreen)
     ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 
     pScreen->CloseScreen = pPriv->CloseScreen;
-    pScreen->CreateScreenResources = pPriv->CreateScreenResources;
 
     free(pPriv);
 
commit d9e99edd4dcf109492abdaa73ccf8f29d5bfd159
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Apr 30 13:49:06 2014 -0400

    glxproxy: Fix memory leak on error path in CreateGLXPixmap (#50281) (v2)
    
    v2: Fix another path spotted by keithp
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/dmx/glxProxy/glxcmds.c b/hw/dmx/glxProxy/glxcmds.c
index 964db40..23c3366 100644
--- a/hw/dmx/glxProxy/glxcmds.c
+++ b/hw/dmx/glxProxy/glxcmds.c
@@ -2009,6 +2009,7 @@ CreateGLXPixmap(__GLXclientState * cl,
         }
         else {
             client->errorValue = (visual ? visual : fbconfigId);
+            free(pGlxPixmap->be_xids);
             free(pGlxPixmap);
             return BadValue;
         }
@@ -2017,6 +2018,7 @@ CreateGLXPixmap(__GLXclientState * cl,
     }
 
     if (!(AddResource(glxpixmapId, __glXPixmapRes, pGlxPixmap))) {
+        free(pGlxPixmap->be_xids);
         free(pGlxPixmap);
         return BadAlloc;
     }
commit dff1f5e1a9608eda2992fc9e3304edee7b5bee9b
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Apr 30 13:49:05 2014 -0400

    dmx: Fix memory leak in dmxBELoadFont (#50281)
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/dmx/dmxfont.c b/hw/dmx/dmxfont.c
index 6b81826..115422d 100644
--- a/hw/dmx/dmxfont.c
+++ b/hw/dmx/dmxfont.c
@@ -397,12 +397,12 @@ dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont)
                    "font-path-related options, see the Xdmx man page.\n");
         }
 
+        free(goodfps);
         if (!dmxIgnoreBadFontPaths ||
             (dmxIgnoreBadFontPaths && dmxSetFontPath(dmxScreen))) {
             /* We still have errors so return with error */
             dmxFreeFontPath(fp);
             XFreeFontPath(oldFontPath);
-            free(goodfps);
             return FALSE;
         }
     }
commit 3dba171f5e82101aa8ea2e47d2253c3410907f6a
Author: Michal Srb <msrb at suse.com>
Date:   Tue Apr 15 18:54:35 2014 +0300

    dri2: Fix detection of wrong prime_id in GetScreenPrime.
    
    Checking the iterating variable ("slave") against null can not detect if the
    xorg_list_for_each_entry finished without break being invoked - slave variable
    will be always non-null. This caused segfault whenever someone tried to use
    DRI_PRIME with incorrect id while having at least one render offloading slave
    configured.
    
    Restructurize the GetScreenPrime to work as expected.
    
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 76708ca..6dd7796 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -156,11 +156,9 @@ GetScreenPrime(ScreenPtr master, int prime_id)
 
         ds = DRI2GetScreen(slave);
         if (ds->prime_id == prime_id)
-            break;
+            return slave;
     }
-    if (!slave)
-        return master;
-    return slave;
+    return master;
 }
 
 static DRI2ScreenPtr
commit c08d2b8ccb0158dbf1f529f80cc3236e66236cce
Author: Alexey Brodkin <Alexey.Brodkin at synopsys.com>
Date:   Thu May 1 15:39:29 2014 +0300

    ARC: Add support for ARC architecture
    
    Xorg server could be built for and run on Synopsys DesignWare ARC cores.
    These changes are required for successful building and execution of the server.
    
    Both little-endian and big-endian flavors of ARC cores are supported.
    
    Signed-off-by: Alexey Brodkin <abrodkin at synopsys.com>
    Acked-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Egbert Eich <eich at freedesktop.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h
index fb95f58..0319de0 100644
--- a/hw/xfree86/common/compiler.h
+++ b/hw/xfree86/common/compiler.h
@@ -1352,7 +1352,7 @@ stl_u(unsigned long val, unsigned int *p)
 #else                           /* ix86 */
 
 #if !defined(__SUNPRO_C)
-#if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__) && !defined(__aarch64__)
+#if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__) && !defined(__aarch64__) && !defined(__arc__)
 #ifdef GCCUSESGAS
 
 /*
@@ -1454,7 +1454,7 @@ inl(unsigned short port)
 
 #endif                          /* GCCUSESGAS */
 
-#else                           /* !defined(FAKEIT) && !defined(__mc68000__)  && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__m32r__) */
+#else                           /* !defined(FAKEIT) && !defined(__mc68000__)  && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__m32r__) && !defined(__arc__) */
 
 static __inline__ void
 outb(unsigned short port, unsigned char val)
diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c
index 47f5abc..40765fc 100644
--- a/hw/xfree86/os-support/linux/lnx_video.c
+++ b/hw/xfree86/os-support/linux/lnx_video.c
@@ -59,7 +59,8 @@ static Bool ExtendedEnabled = FALSE;
       !defined(__mips__) && \
       !defined(__nds32__) && \
       !defined(__arm__) && \
-      !defined(__aarch64__)
+      !defined(__aarch64__) && \
+      !defined(__arc__)
 
 /*
  * Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare
diff --git a/include/servermd.h b/include/servermd.h
index 11f6c10..2d1ccb1 100644
--- a/include/servermd.h
+++ b/include/servermd.h
@@ -300,6 +300,19 @@ SOFTWARE.
 
 #endif                          /* __aarch64__ */
 
+#if defined(__arc__)
+
+#if defined(__BIG_ENDIAN__)
+#define IMAGE_BYTE_ORDER	MSBFirst
+#define BITMAP_BIT_ORDER	MSBFirst
+#else
+#define IMAGE_BYTE_ORDER	LSBFirst
+#define BITMAP_BIT_ORDER	LSBFirst
+#endif
+#define GLYPHPADBYTES		4
+
+#endif                          /* ARC */
+
 /* size of buffer to use with GetImage, measured in bytes. There's obviously
  * a trade-off between the amount of heap used and the number of times the
  * ddx routine has to be called.
commit 01e18af17f8dc91451fbd0902049045afd1cea7e
Author: Dave Airlie <airlied at redhat.com>
Date:   Mon May 12 14:55:04 2014 -0700

    rrcrtc: brackets are hard, lets go shopping.
    
    Slaving two outputs on a secondary GPU to a primary GPU testing
    picked this up, in that we'd try to resize to the totally the
    wrong thing, then as usual segfault in the rotation code.
    
    Signed-off-by: Dave Airlie <airlied at redhat.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 6da698e..69b3ecf 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -476,7 +476,7 @@ rrCheckPixmapBounding(ScreenPtr pScreen,
 
     xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
         rrScrPrivPtr    slave_priv = rrGetScrPriv(slave);
-        for (c = 0; c < slave_priv->numCrtcs; c++)
+        for (c = 0; c < slave_priv->numCrtcs; c++) {
             if (slave_priv->crtcs[c] == rr_crtc) {
                 newbox.x1 = x;
                 newbox.x2 = x + w;
@@ -491,8 +491,9 @@ rrCheckPixmapBounding(ScreenPtr pScreen,
                 newbox.y1 = slave_priv->crtcs[c]->y;
                 newbox.y2 = slave_priv->crtcs[c]->y + slave_priv->crtcs[c]->mode->mode.height;
             }
-        RegionInit(&new_crtc_region, &newbox, 1);
-        RegionUnion(&total_region, &total_region, &new_crtc_region);
+            RegionInit(&new_crtc_region, &newbox, 1);
+            RegionUnion(&total_region, &total_region, &new_crtc_region);
+        }
     }
 
     newsize = RegionExtents(&total_region);
commit 6dd86f3cba7cca67f3a9102db2e90722d32a34cb
Author: Eric Anholt <eric at anholt.net>
Date:   Mon May 5 17:01:14 2014 -0700

    glamor: Don't forget to check whether we can fall back in polysegment.
    
    Part of the _nf contract is that glamor will only return FALSE if
    glamor has checked that UXA can actually map the pixmaps (UXA only
    allocates the BO itself in the screen pixmap and DRI2 cases, and can't
    map it otherwise).  Fixes server segfaults zooming in and out of
    libreoffice spreadsheets.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_segment.c b/glamor/glamor_segment.c
index 84b27ac..53f7da0 100644
--- a/glamor/glamor_segment.c
+++ b/glamor/glamor_segment.c
@@ -26,14 +26,19 @@ Bool
 glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc, int nseg,
                        xSegment *seg)
 {
-    return FALSE;
+    if (glamor_ddx_fallback_check_pixmap(drawable) &&
+        glamor_ddx_fallback_check_gc(gc)) {
+        return FALSE;
+    }
+
+    miPolySegment(drawable, gc, nseg, seg);
+
+    return TRUE;
 }
 
 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 fb24ac0a2c317099bdf7d1d8e4b7c443e3ee644f
Author: Laércio de Sousa <lbsousajr at gmail.com>
Date:   Fri May 9 09:09:16 2014 -0300

    xfree86: fix warnings after MatchSeat patch
    
    This patch fixes some compile warnings that arise after
    commit 7070ebeebaca1b51f8a2801989120784a1c374ae
    (xfree86: add new key MatchSeat to xorg.conf sections "Device", "Screen", and "ServerLayout")
    available at git repository
    git://people.freedesktop.org/~whot/xserver for-keith
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 5d17567..2adef44 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -232,16 +232,17 @@ xf86ValidateFontPath(char *path)
     return tmp_path;
 }
 
-#define FIND_SUITABLE(pointertype, listhead, ptr)                               \
-    {                                                                           \
-        pointertype l, p;                                                       \
-                                                                                \
-        for (l = listhead, p = NULL; !p && l; l = (pointertype) l->list.next) { \
-            if (! l->match_seat || SeatId && xf86nameCompare(l->match_seat, SeatId) == 0) \
-                p = l;                                                          \
-        }                                                                       \
-        ptr = p;                                                                \
-    }
+#define FIND_SUITABLE(pointertype, listhead, ptr)                                            \
+    do {                                                                                     \
+        pointertype _l, _p;                                                                  \
+                                                                                             \
+        for (_l = (listhead), _p = NULL; !_p && _l; _l = (pointertype)_l->list.next) {       \
+            if (!_l->match_seat || (SeatId && xf86nameCompare(_l->match_seat, SeatId) == 0)) \
+                _p = _l;                                                                     \
+        }                                                                                    \
+                                                                                             \
+        (ptr) = _p;                                                                          \
+    } while(0)
 
 /*
  * use the datastructure that the parser provides and pick out the parts
@@ -2368,6 +2369,7 @@ xf86HandleConfigFile(Bool autoconfig)
     const char *scanptr;
     Bool singlecard = 0;
     Bool implicit_layout = FALSE;
+    XF86ConfLayoutPtr layout;
 
     if (!autoconfig) {
         char *filename, *dirname, *sysdirname;
@@ -2443,8 +2445,6 @@ xf86HandleConfigFile(Bool autoconfig)
      */
 
     /* First check if a layout section is present, and if it is valid. */
-    XF86ConfLayoutPtr layout;
-
     FIND_SUITABLE(XF86ConfLayoutPtr, xf86configptr->conf_layout_lst, layout);
     if (layout == NULL || xf86ScreenName != NULL) {
         XF86ConfScreenPtr screen;
commit bbfed454b2a0fd5e2723524d145cb7c6e5aa9193
Author: Eric Anholt <eric at anholt.net>
Date:   Thu May 8 08:45:22 2014 -0700

    glamor: Stop disabling asserts by default.
    
    Disabling asserts is something the user gets to manage.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 96635be..c56c559 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -30,9 +30,6 @@
 #include "dix-config.h"
 
 #include <xorg-server.h>
-#ifndef DEBUG
-#define NDEBUG
-#endif
 #include "glamor.h"
 
 #include <epoxy/gl.h>
commit 8e2fefe3ef247f8b5d74e32e8d37c619b06fc60c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Apr 29 16:52:01 2014 +1000

    Xi: don't copy a DeviceEvent into an InternalEvent
    
    ==26141== Invalid read of size 8
    ==26141==    at 0x58FAEA: DeliverEmulatedMotionEvent (exevents.c:1484)
    
    An InternalEvent is bigger than a DeviceEvent, thus copying one to the other
    reads past the allocated boundary. Shouldn't have any real effect since we
    shouldn't access anything past the DeviceEvent boundary if the event type is
    correct.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 9c207eb..02530bd 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1469,7 +1469,7 @@ static void
 DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
                            InternalEvent *ev)
 {
-    InternalEvent motion;
+    DeviceEvent motion;
 
     if (ti->num_listeners) {
         ClientPtr client;
@@ -1481,11 +1481,11 @@ DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
             ti->listeners[0].type != LISTENER_POINTER_GRAB)
             return;
 
-        motion = *ev;
-        motion.any.type = ET_TouchUpdate;
-        motion.device_event.detail.button = 0;
+        motion = ev->device_event;
+        motion.type = ET_TouchUpdate;
+        motion.detail.button = 0;
 
-        if (!RetrieveTouchDeliveryData(dev, ti, &motion,
+        if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
                                        &ti->listeners[0], &client, &win, &grab,
                                        &mask))
             return;
@@ -1500,18 +1500,18 @@ DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
             }
         }
 
-        DeliverTouchEmulatedEvent(dev, ti, &motion, &ti->listeners[0], client,
+        DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
                                   win, grab, mask);
     }
     else {
         InternalEvent button;
         int converted;
 
-        converted = TouchConvertToPointerEvent(ev, &motion, &button);
+        converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
 
         BUG_WARN(converted == 0);
         if (converted)
-            ProcessOtherEvent(&motion, dev);
+            ProcessOtherEvent((InternalEvent*)&motion, dev);
     }
 }
 
commit d7ac9aff061f2961e6b76557dda97b57988ce362
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Apr 30 10:55:26 2014 +1000

    mi: start calculating the sprite trace from the first child of root
    
    Introduced in
    73698d41e41ce76bef2d9a90b46ac0c24ae148dd "Make XYToWindow a screen function"
    
    Moving the code into miwindow.c changed the start of the loop from
    RootWindow()->firstChild to DeepestSpriteWindow(). This function is only
    supposed to be called from miXYToWindow which resets spriteTraceGood to 1,
    thus DeepestSpriteWindow() is always the root window anyway.
    What got dropped was the firstChild as the first window to handle, so we may
    end up with the root window twice in the sprite trace.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/mi/miwindow.c b/mi/miwindow.c
index 951b8c5..57de91b 100644
--- a/mi/miwindow.c
+++ b/mi/miwindow.c
@@ -766,7 +766,7 @@ miSpriteTrace(SpritePtr pSprite, int x, int y)
     WindowPtr pWin;
     BoxRec box;
 
-    pWin = DeepestSpriteWin(pSprite);
+    pWin = DeepestSpriteWin(pSprite)->firstChild;
     while (pWin) {
         if ((pWin->mapped) &&
             (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
commit d60724b752613ce2ad11c6ae102bf4513f9768ff
Merge: a5b9757 15460ea
Author: Keith Packard <keithp at keithp.com>
Date:   Thu May 8 12:58:41 2014 -0700

    Merge commit 'who/for-keith'
    
    Skipping two unreviewed patches; will mark them reviewed and cherry pick

commit a5b9757142a2ab471ca26651dce9cc5f5e351f3d
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 25 15:07:03 2014 -0700

    glamor: Publish change_window_attributes and copy_window
    
    Because uxa doesn't just use glamor directly, it keeps these two
    functions from being wrapped so that they get called
    automatically. Publishing these will allow uxa to call them directly.
    
    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.h b/glamor/glamor.h
index e63762b..b0f2212 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -321,6 +321,9 @@ extern _X_EXPORT int glamor_create_gc(GCPtr gc);
 extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes,
                                          DrawablePtr drawable);
 
+extern Bool _X_EXPORT glamor_change_window_attributes(WindowPtr pWin, unsigned long mask);
+extern void _X_EXPORT glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region);
+
 /* 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 a2a21fc..96635be 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -626,10 +626,6 @@ void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc,
                         BoxPtr box, int nbox, int dx, int dy, Bool reverse,
                         Bool upsidedown, Pixel bitplane, void *closure);
 
-/* glamor_copywindow.c */
-void glamor_copy_window(WindowPtr win, DDXPointRec old_origin,
-                        RegionPtr src_region);
-
 /* glamor_core.c */
 Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access);
 void glamor_finish_access(DrawablePtr drawable);
@@ -670,7 +666,6 @@ glamor_pixmap_fbo *glamor_es2_pixmap_read_prepare(PixmapPtr source, int x,
 
 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);
 
 /* glamor_fill.c */
commit 4711182033ec579caff8c930d420f90ecdbe54cf
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 25 20:25:56 2014 -0700

    glamor: Work around libXfont when it fails to use defaultChar
    
    GetGlyphs is supposed to always return the full list of characters
    when there is a default character available. However, if an
    application opens a 16-bit two dimensional font and then draws with
    8-bit requests, the bitmapGetGlyphs function in libXfont versions up
    through 1.4.7 will return zero glyphs if there is no 0th row.
    
    While this is a bug in libXfont and should be fixed there, it's easy
    to protect glamor from it by simply falling through to the case that
    handles GetGlyphs failures for fonts without a default character.
    
    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_text.c b/glamor/glamor_text.c
index fdee08e..6e02b9a 100644
--- a/glamor/glamor_text.c
+++ b/glamor/glamor_text.c
@@ -37,6 +37,7 @@ glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font,
     unsigned long nglyphs;
     FontEncoding encoding;
     int char_step;
+    int c;
 
     if (sixteen) {
         char_step = 2;
@@ -49,7 +50,7 @@ glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font,
         encoding = Linear8Bit;
     }
 
-    /* If the font has a default character, then we don't have to
+    /* If the font has a default character, then we shouldn'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.
@@ -57,15 +58,28 @@ glamor_get_glyphs(FontPtr font, glamor_font_t *glamor_font,
     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;
-        }
+
+        /* Make sure it worked. There's a bug in libXfont through
+         * version 1.4.7 which would cause it to fail when the font is
+         * a 2D font without a first row, and the application sends a
+         * 1-d request. In this case, libXfont would return zero
+         * glyphs, even when the font had a default character.
+         *
+         * It's easy enough for us to work around that bug here by
+         * simply checking the returned nglyphs and falling through to
+         * the one-at-a-time code below. Not doing this check would
+         * result in uninitialized memory accesses in the rendering code.
+         */
+        if (nglyphs == count)
+            return;
+    }
+
+    for (c = 0; c < count; c++) {
+        GetGlyphs(font, 1, (unsigned char *) chars,
+                  encoding, &nglyphs, &charinfo[c]);
+        if (!nglyphs)
+            charinfo[c] = NULL;
+        chars += char_step;
     }
 }
 
commit 91767a32874790f8a8c7340be0e81a0b719ca4f6
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 25 23:38:35 2014 -0700

    glamor: Fix uxa-entry point for ImageText16
    
    Was interpreting the incoming chars as 8-bits instead of 16-bits,
    resulting in the wrong characters being drawn.
    
    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_text.c b/glamor/glamor_text.c
index 395116d..fdee08e 100644
--- a/glamor/glamor_text.c
+++ b/glamor/glamor_text.c
@@ -508,7 +508,7 @@ 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);
+    return glamor_image_text(drawable, gc, x, y, count, (char *) chars, TRUE);
 }
 
 void
commit 15460eaed28b5353a94a17091d7795cfaeda9146
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri May 2 14:14:58 2014 +1000

    systemd-logind: let the logind code decided whether to close an fd
    
    We can only request one fd per device from systemd-logind. If a fd is re-used
    by the same device, releasing the fd from one device doesn't mean we can close
    it. The systemd code knows when it's really released, so let it close the fd.
    
    Test case: xorg.conf section for an input device with hotplugging enabled.
    evdev detects the duplicate and closes the hotplugged device, which closes the
    fd. The other instance of evdev thinks the fd is still valid so now you're
    playing a double lottery. First, which client(s) will get the evdev fd?
    Second, which requests will be picked up by evdev and which ones will be
    picked up by the client? You'll never know, but the fun is in finding out.
    
    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 def7f16..5514516 100644
--- a/config/config.c
+++ b/config/config.c
@@ -250,8 +250,6 @@ config_odev_free_attributes(struct OdevAttributes *attribs)
         free(iter);
     }
 
-    if (fd != -1) {
-        systemd_logind_release_fd(major, minor);
-        close(fd);
-    }
+    if (fd != -1)
+        systemd_logind_release_fd(major, minor, fd);
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index bc6b73f..4e8060b 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -770,10 +770,8 @@ 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);
-    }
+    if (pInp->flags & XI86_SERVER_FD)
+        systemd_logind_release_fd(pInp->major, pInp->minor, pInp->fd);
 
     /* Remove the entry from the list. */
     if (pInp == xf86InputDevs)
@@ -873,8 +871,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
                             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);
+                systemd_logind_release_fd(pInfo->major, pInfo->minor, fd);
                 return BadMatch;
             }
             pInfo->fd = fd;
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 4e80f9e..dd118a2 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -340,8 +340,7 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp,
             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);
+            systemd_logind_release_fd(major, minor, fd);
             config_odev_add_int_attribute(dev->attribs, ODEV_ATTRIB_FD, -1);
             dev->flags &= ~XF86_PDEV_SERVER_FD;
         }
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index dbd7aa0..308275a 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -37,7 +37,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
         if (paused) {
             LogMessage(X_ERROR,
                     "Error systemd-logind returned paused fd for drm node\n");
-            systemd_logind_release_fd(major, minor);
+            systemd_logind_release_fd(major, minor, -1);
             return FALSE;
         }
         config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd);
diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c
index ed670a8..73a8d55 100644
--- a/hw/xfree86/os-support/linux/systemd-logind.c
+++ b/hw/xfree86/os-support/linux/systemd-logind.c
@@ -162,7 +162,7 @@ cleanup:
 }
 
 void
-systemd_logind_release_fd(int _major, int _minor)
+systemd_logind_release_fd(int _major, int _minor, int fd)
 {
     struct systemd_logind_info *info = &logind_info;
     InputInfoPtr pInfo;
@@ -174,7 +174,7 @@ systemd_logind_release_fd(int _major, int _minor)
     int matches = 0;
 
     if (!info->session || major == 0)
-        return;
+        goto close;
 
     /* 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. */
@@ -218,6 +218,9 @@ cleanup:
     if (reply)
         dbus_message_unref(reply);
     dbus_error_free(&error);
+close:
+    if (fd != -1)
+        close(fd);
 }
 
 int
diff --git a/include/systemd-logind.h b/include/systemd-logind.h
index 06dd031..a4067d0 100644
--- a/include/systemd-logind.h
+++ b/include/systemd-logind.h
@@ -30,14 +30,14 @@
 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);
+void systemd_logind_release_fd(int major, int minor, int fd);
 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, paus) -1
-#define systemd_logind_release_fd(major, minor)
+#define systemd_logind_release_fd(major, minor, fd) close(fd)
 #define systemd_logind_controls_session() 0
 #define systemd_logind_vtenter()
 #endif
commit 42a4873cc7fe0c7a729e48f806e877c4dac5c07f
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Apr 30 09:32:29 2014 -0700

    hw/xfree86: Video Driver ABI version 18.0
    
    With the change in the cursor interface in
    4c3932620c29c91dfbbc8eb09c84efcaa7ec873e, we need to bump the video
    driver ABI number to ensure that drivers are rebuilt to match the new
    interface.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 62ac95d..b848f53 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(17, 0)
+#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(18, 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)
commit a6f5ffd5879e7fb052d343592951cc476b699bb4
Author: Laércio de Sousa <lbsousajr at gmail.com>
Date:   Thu Apr 3 11:19:15 2014 -0300

    xfree86: add short description about MatchSeat key in xorg.conf man page
    
    Signed-off-by: Laércio de Sousa <lbsousajr at gmail.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index 6d2652e..cadd87b 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -1378,6 +1378,14 @@ for the regular text mode.
 The frequency is specified in MHz.
 This is rarely used.
 .TP 7
+.BI "MatchSeat  " "seat\-id"
+Only apply this
+.B Device
+section if X server was started with
+.B -seat
+.I seat\-id
+option.
+.TP 7
 .BI "Option \*qModeDebug\*q \*q" boolean \*q
 Enable printing of additional debugging information about modesetting to
 the server log.
@@ -1900,6 +1908,14 @@ The only case where there is even a choice in this value is for depth 24,
 where some hardware supports both a packed 24 bit framebuffer layout and a
 sparse 32 bit framebuffer layout.
 .TP 7
+.BI "MatchSeat  " "seat\-id"
+Only apply this
+.B Screen
+section if X server was started with
+.B -seat
+.I seat\-id
+option.
+.TP 7
 .B Options
 Various
 .B Option
@@ -2295,6 +2311,14 @@ and the first two should normally be used to indicate the core pointer
 and core keyboard devices respectively.
 .RE
 .TP 7
+.BI "MatchSeat  " "seat\-id"
+Only apply this
+.B ServerLayout
+section if X server was started with
+.B -seat
+.I seat\-id
+option.
+.TP 7
 .B Options
 In addition to the following, any option permitted in the
 .B ServerFlags
commit 7070ebeebaca1b51f8a2801989120784a1c374ae
Author: Oleg Samarin <osamarin68 at gmail.com>
Date:   Thu Apr 3 11:19:14 2014 -0300

    xfree86: add new key MatchSeat to xorg.conf sections "Device", "Screen", and "ServerLayout"
    
    This patch introduces a new key MatchSeat in xorg.conf (also applies to
    any .conf file in xorg.conf.d). It will allow targeting a given
    "Device", "Screen", and/or "ServerLayout" section to a particular
    seat only (specified by option "-seat" in X server command line),
    so that other seats won't be affected.
    
    Without this patch, one needs to write a separate xorg.conf.custom
    file and pass it to X server via "-config" option, if one wants that
    these settings only apply for the right seat. However, in some cases,
    this solution is undesirable or even impossible (e.g. when using GDM,
    which doesn't allow X server command line customization).
    
    Example file (/etc/X11/xorg.conf.d/seat1.conf), which would be ignored
    by X server unless it was started with "-seat seat1" option:
    
    Section "Device"
        Identifier "card0"
        Driver "nvidia"
        Option "NoLogo" "True"
        MatchSeat "seat1"
    EndSection
    
    Signed-off-by: Oleg Samarin <osamarin68 at gmail.com>
    Signed-off-by: Laércio de Sousa <lbsousajr at gmail.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index 542d5ab..5d17567 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -232,6 +232,17 @@ xf86ValidateFontPath(char *path)
     return tmp_path;
 }
 
+#define FIND_SUITABLE(pointertype, listhead, ptr)                               \
+    {                                                                           \
+        pointertype l, p;                                                       \
+                                                                                \
+        for (l = listhead, p = NULL; !p && l; l = (pointertype) l->list.next) { \
+            if (! l->match_seat || SeatId && xf86nameCompare(l->match_seat, SeatId) == 0) \
+                p = l;                                                          \
+        }                                                                       \
+        ptr = p;                                                                \
+    }
+
 /*
  * use the datastructure that the parser provides and pick out the parts
  * that we need at this point
@@ -1580,8 +1591,11 @@ configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
      * config file, or - if it is NULL - configScreen autogenerates one for
      * us */
     if (!count) {
+        XF86ConfScreenPtr screen;
+
+        FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
         slp[0].screen = xnfcalloc(1, sizeof(confScreenRec));
-        if (!configScreen(slp[0].screen, xf86configptr->conf_screen_lst,
+        if (!configScreen(slp[0].screen, screen,
                           0, X_CONFIG)) {
             free(slp[0].screen);
             free(slp);
@@ -1821,7 +1835,7 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum,
      * set it to NULL so that the section can be autoconfigured later */
     screenp->device = xnfcalloc(1, sizeof(GDevRec));
     if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) {
-        conf_screen->scrn_device = xf86configptr->conf_device_lst;
+        FIND_SUITABLE (XF86ConfDevicePtr, xf86configptr->conf_device_lst, conf_screen->scrn_device);
         xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n"
                 "\tUsing the first device section listed.\n", screenp->id);
     }
@@ -2429,14 +2443,19 @@ xf86HandleConfigFile(Bool autoconfig)
      */
 
     /* First check if a layout section is present, and if it is valid. */
+    XF86ConfLayoutPtr layout;
+
+    FIND_SUITABLE(XF86ConfLayoutPtr, xf86configptr->conf_layout_lst, layout);
+    if (layout == NULL || xf86ScreenName != NULL) {
+        XF86ConfScreenPtr screen;
 
-    if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) {
         if (xf86ScreenName == NULL) {
             xf86Msg(X_DEFAULT,
                     "No Layout section.  Using the first Screen section.\n");
         }
+        FIND_SUITABLE (XF86ConfScreenPtr, xf86configptr->conf_screen_lst, screen);
         if (!configImpliedLayout(&xf86ConfigLayout,
-                                 xf86configptr->conf_screen_lst,
+                                 screen,
                                  xf86configptr)) {
             xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
             return CONFIG_PARSE_ERROR;
@@ -2451,16 +2470,13 @@ xf86HandleConfigFile(Bool autoconfig)
             if (optlist && xf86FindOption(optlist, "defaultserverlayout"))
                 dfltlayout =
                     xf86SetStrOption(optlist, "defaultserverlayout", NULL);
-            if (!configLayout
-                (&xf86ConfigLayout, xf86configptr->conf_layout_lst,
-                 dfltlayout)) {
+            if (!configLayout(&xf86ConfigLayout, layout, dfltlayout)) {
                 xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
                 return CONFIG_PARSE_ERROR;
             }
         }
         else {
-            if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst,
-                              NULL)) {
+            if (!configLayout(&xf86ConfigLayout, layout, NULL)) {
                 xf86Msg(X_ERROR, "Unable to determine the screen layout\n");
                 return CONFIG_PARSE_ERROR;
             }
diff --git a/hw/xfree86/parser/Device.c b/hw/xfree86/parser/Device.c
index 073171f..d3ac293 100644
--- a/hw/xfree86/parser/Device.c
+++ b/hw/xfree86/parser/Device.c
@@ -71,6 +71,7 @@ xf86ConfigSymTabRec DeviceTab[] = {
     {RAMDAC, "ramdac"},
     {DACSPEED, "dacspeed"},
     {CLOCKS, "clocks"},
+    {MATCHSEAT, "matchseat"},
     {OPTION, "option"},
     {VIDEORAM, "videoram"},
     {BIOSBASE, "biosbase"},
@@ -216,6 +217,11 @@ xf86parseDeviceSection(void)
                 Error(NUMBER_MSG, "TextClockFreq");
             ptr->dev_textclockfreq = (int) (xf86_lex_val.realnum * 1000.0 + 0.5);
             break;
+        case MATCHSEAT:
+            if (xf86getSubToken(&(ptr->dev_comment)) != STRING)
+                Error(QUOTE_MSG, "MatchSeat");
+            ptr->match_seat = xf86_lex_val.str;
+            break;
         case OPTION:
             ptr->dev_option_lst = xf86parseOption(ptr->dev_option_lst);
             break;
diff --git a/hw/xfree86/parser/Layout.c b/hw/xfree86/parser/Layout.c
index 7be746f..994b31a 100644
--- a/hw/xfree86/parser/Layout.c
+++ b/hw/xfree86/parser/Layout.c
@@ -70,6 +70,7 @@ static xf86ConfigSymTabRec LayoutTab[] = {
     {ENDSECTION, "endsection"},
     {SCREEN, "screen"},
     {IDENTIFIER, "identifier"},
+    {MATCHSEAT, "matchseat"},
     {INACTIVE, "inactive"},
     {INPUTDEVICE, "inputdevice"},
     {OPTION, "option"},
@@ -109,6 +110,11 @@ xf86parseLayoutSection(void)
             ptr->lay_identifier = xf86_lex_val.str;
             has_ident = TRUE;
             break;
+        case MATCHSEAT:
+            if (xf86getSubToken(&(ptr->lay_comment)) != STRING)
+                Error(QUOTE_MSG, "MatchSeat");
+            ptr->match_seat = xf86_lex_val.str;
+            break;
         case INACTIVE:
         {
             XF86ConfInactivePtr iptr;
diff --git a/hw/xfree86/parser/Screen.c b/hw/xfree86/parser/Screen.c
index fecd57c..0e9746a 100644
--- a/hw/xfree86/parser/Screen.c
+++ b/hw/xfree86/parser/Screen.c
@@ -198,6 +198,7 @@ xf86parseDisplaySubSection(void)
 static xf86ConfigSymTabRec ScreenTab[] = {
     {ENDSECTION, "endsection"},
     {IDENTIFIER, "identifier"},
+    {MATCHSEAT, "matchseat"},
     {OBSDRIVER, "driver"},
     {MDEVICE, "device"},
     {MONITOR, "monitor"},
@@ -236,6 +237,11 @@ xf86parseScreenSection(void)
                 Error(ONLY_ONE_MSG, "Identifier or Driver");
             has_ident = TRUE;
             break;
+        case MATCHSEAT:
+            if (xf86getSubToken(&(ptr->scrn_comment)) != STRING)
+                Error(QUOTE_MSG, "MatchSeat");
+            ptr->match_seat = xf86_lex_val.str;
+            break;
         case OBSDRIVER:
             if (xf86getSubToken(&(ptr->scrn_comment)) != STRING)
                 Error(QUOTE_MSG, "Driver");
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index 8f855ac..c95423a 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -224,6 +224,7 @@ typedef struct {
     int dev_screen;
     XF86OptionPtr dev_option_lst;
     char *dev_comment;
+    char *match_seat;
 } XF86ConfDeviceRec, *XF86ConfDevicePtr;
 
 typedef struct {
@@ -275,6 +276,7 @@ typedef struct {
     XF86OptionPtr scrn_option_lst;
     char *scrn_comment;
     int scrn_virtualX, scrn_virtualY;
+    char *match_seat;
 } XF86ConfScreenRec, *XF86ConfScreenPtr;
 
 typedef struct {
@@ -366,6 +368,7 @@ typedef struct {
     XF86ConfInactivePtr lay_inactive_lst;
     XF86ConfInputrefPtr lay_input_lst;
     XF86OptionPtr lay_option_lst;
+    char *match_seat;
     char *lay_comment;
 } XF86ConfLayoutRec, *XF86ConfLayoutPtr;
 
diff --git a/hw/xfree86/parser/xf86tokens.h b/hw/xfree86/parser/xf86tokens.h
index f751b7b..5c01ce7 100644
--- a/hw/xfree86/parser/xf86tokens.h
+++ b/hw/xfree86/parser/xf86tokens.h
@@ -87,6 +87,7 @@ typedef enum {
     VENDOR,
     DASH,
     COMMA,
+    MATCHSEAT,
     OPTION,
     COMMENT,
 
commit 29b1484bb9555e45067669cbfe68a3c40596f4ff
Author: Laércio de Sousa <lbsousajr at gmail.com>
Date:   Thu Apr 3 11:19:13 2014 -0300

    xfree86: allow fallback to PCI bus probe for graphics devices on non-seat0 X servers (#66851)
    
    Currently non-seat0 X servers only probe platform bus for graphics devices,
    which is OK for most KMS-compliant drivers. However, for non-KMS drivers
    (like NVIDIA proprietary ones), graphics devices can't be reached
    by platform bus probe, resulting in a "No devices detected" error.
    
    This patch allows a fallback to PCI bus probe for non-seat0 X servers
    in case no platform bus graphics device is found.
    
    Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66851
    
    Signed-off-by: Laércio de Sousa <lbsousajr at gmail.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c
index 507c57d..b3b3f8c 100644
--- a/hw/xfree86/common/xf86Bus.c
+++ b/hw/xfree86/common/xf86Bus.c
@@ -81,7 +81,7 @@ xf86CallDriverProbe(DriverPtr drv, Bool detect_only)
     if (drv->platformProbe != NULL) {
         foundScreen = xf86platformProbeDev(drv);
     }
-    if (ServerIsNotSeat0())
+    if (ServerIsNotSeat0() && foundScreen)
         return foundScreen;
 #endif
 
@@ -201,7 +201,7 @@ xf86BusProbe(void)
 {
 #ifdef XSERVER_PLATFORM_BUS
     xf86platformProbe();
-    if (ServerIsNotSeat0())
+    if (ServerIsNotSeat0() && xf86_num_platform_devices > 0)
         return;
 #endif
 #ifdef XSERVER_LIBPCIACCESS
commit 2535b76c0d32bc1dd0ddaca06a419a68a4757df1
Author: Robert Ancell <robert.ancell at canonical.com>
Date:   Wed Apr 23 08:19:35 2014 +1200

    os: Add -displayfd into -help text
    
    Add -displayfd into -help text. It was mentioned in the man page but seem to have been missed from the -help text.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/os/utils.c b/os/utils.c
index bc5e7df..ed7581e 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -529,6 +529,7 @@ UseMsg(void)
     ErrorF("-cc int                default color visual class\n");
     ErrorF("-nocursor              disable the cursor\n");
     ErrorF("-core                  generate core dump on fatal error\n");
+    ErrorF("-displayfd fd          file descriptor to write display number to when ready to connect\n");
     ErrorF("-dpi int               screen resolution in dots per inch\n");
 #ifdef DPMSExtension
     ErrorF("-dpms                  disables VESA DPMS monitor control\n");
commit a26578dbb93dbaab1910b52f9fa1c87f8c9e6d1e
Author: Ray Strode <rstrode at redhat.com>
Date:   Thu Apr 24 13:38:29 2014 -0400

    selinux: don't checkout for AVCs on select() EINTR
    
    wakeup handlers are called even when select() returns EINTR,
    and when they're called the passed fd set is undefined.
    
    This commit fixes the selinux wakeup handler to avoid checking
    for AVCs over the netlink socket spuriously.
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Ray Strode <rstrode at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/xselinux_hooks.c b/Xext/xselinux_hooks.c
index 376d575..48219a9 100644
--- a/Xext/xselinux_hooks.c
+++ b/Xext/xselinux_hooks.c
@@ -812,9 +812,9 @@ SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask)
 }
 
 static void
-SELinuxWakeupHandler(void *data, int err, void *read_mask)
+SELinuxWakeupHandler(void *data, int num_fds, void *read_mask)
 {
-    if (FD_ISSET(netlink_fd, (fd_set *) read_mask))
+    if (num_fds > 0 && FD_ISSET(netlink_fd, (fd_set *) read_mask))
         avc_netlink_check_nb();
 }
 
commit bcb17b99873f020f2639b860ce99d260def0cd97
Author: Ray Strode <rstrode at redhat.com>
Date:   Thu Apr 24 13:38:28 2014 -0400

    dbus: don't dispatch dbus events on select() EINTR
    
    wakeup handlers are called even when select() returns EINTR,
    and when they're called the passed fd set is undefined.
    
    This commit fixes the dbus wakeup handler to avoid dispatching
    into dbus spuriously.
    
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Ray Strode <rstrode at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/config/dbus-core.c b/config/dbus-core.c
index b0fd92d..8351ea4 100644
--- a/config/dbus-core.c
+++ b/config/dbus-core.c
@@ -48,11 +48,11 @@ static struct dbus_core_info bus_info;
 static CARD32 reconnect_timer(OsTimerPtr timer, CARD32 time, void *arg);
 
 static void
-wakeup_handler(void *data, int err, void *read_mask)
+wakeup_handler(void *data, int num_fds, void *read_mask)
 {
     struct dbus_core_info *info = data;
 
-    if (info->connection && FD_ISSET(info->fd, (fd_set *) read_mask)) {
+    if (info->connection && num_fds > 0 && FD_ISSET(info->fd, (fd_set *) read_mask)) {
         do {
             dbus_connection_read_write_dispatch(info->connection, 0);
         } while (info->connection &&
commit 6bd7ad914470322ddd02b50078e159234ebec643
Merge: b92a928 e06fbe4
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 29 09:37:37 2014 -0700

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

commit e06fbe4dc81110e01d36f958849c4ab5f2a9df0e
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Apr 28 07:57:00 2014 +1000

    dix: remove a now-superfluous comment
    
    Obsolete since 93945b0a74aa8156a88f52b8ba77f1210042f396
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 125a0ee..7e7a1c9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4260,12 +4260,6 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
                                              thisDev);
     }
     if (!deliveries) {
-        /* XXX: In theory, we could pass the internal events through to
-         * everything and only convert just before hitting the wire. We can't
-         * do that yet, so DGE is the last stop for internal events. From here
-         * onwards, we deal with core/XI events.
-         */
-
         sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
         /* try core event */
         if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
commit 6a848122def0f2a439e21c50f22814db11760132
Author: Michal Srb <msrb at suse.com>
Date:   Wed Apr 2 17:14:05 2014 +0300

    input: Remove invalid bug checks.
    
    Commit 2f1aedcaed8fd99b823d451bf1fb02330c078f67 added several bug checks. Some
    of them are not correct.
    
    Checks in Init(Ptr|String|Bell|Led|Integer)FeedbackClassDeviceStruct verify
    that no feedback struct was set yet, but that is not required. If any feedback
    structs are already present, the function will chain them behind the new one.
    
    Signed-off-by: Michal Srb <msrb at suse.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/devices.c b/dix/devices.c
index ab923d5..73f60f4 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1475,7 +1475,6 @@ InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
     PtrFeedbackPtr feedc;
 
     BUG_RETURN_VAL(dev == NULL, FALSE);
-    BUG_RETURN_VAL(dev->ptrfeed != NULL, FALSE);
 
     feedc = malloc(sizeof(PtrFeedbackClassRec));
     if (!feedc)
@@ -1519,7 +1518,6 @@ InitStringFeedbackClassDeviceStruct(DeviceIntPtr dev,
     StringFeedbackPtr feedc;
 
     BUG_RETURN_VAL(dev == NULL, FALSE);
-    BUG_RETURN_VAL(dev->stringfeed != NULL, FALSE);
 
     feedc = malloc(sizeof(StringFeedbackClassRec));
     if (!feedc)
@@ -1556,7 +1554,6 @@ InitBellFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc,
     BellFeedbackPtr feedc;
 
     BUG_RETURN_VAL(dev == NULL, FALSE);
-    BUG_RETURN_VAL(dev->bell != NULL, FALSE);
 
     feedc = malloc(sizeof(BellFeedbackClassRec));
     if (!feedc)
@@ -1578,7 +1575,6 @@ InitLedFeedbackClassDeviceStruct(DeviceIntPtr dev, LedCtrlProcPtr controlProc)
     LedFeedbackPtr feedc;
 
     BUG_RETURN_VAL(dev == NULL, FALSE);
-    BUG_RETURN_VAL(dev->leds != NULL, FALSE);
 
     feedc = malloc(sizeof(LedFeedbackClassRec));
     if (!feedc)
@@ -1601,7 +1597,6 @@ InitIntegerFeedbackClassDeviceStruct(DeviceIntPtr dev,
     IntegerFeedbackPtr feedc;
 
     BUG_RETURN_VAL(dev == NULL, FALSE);
-    BUG_RETURN_VAL(dev->intfeed != NULL, FALSE);
 
     feedc = malloc(sizeof(IntegerFeedbackClassRec));
     if (!feedc)
commit b92a9289fef4831e9af69e5f6f64b5454f550559
Author: Thierry Reding <thierry.reding at gmail.com>
Date:   Wed Feb 12 17:11:40 2014 +0100

    xfree86: int10: Fix build on ARM
    
    Commit 7353ec7cb6fc235b03e59e35425201429c83ee72 "xfree86: Switch int10
    code to stdint types" uses designated initializers to setup the fields
    of the X86EMU_pioFuncs.
    
    This breaks compilation on ARM, since out{b,w,l}() are redefined using
    the preprocessor and therefore cause the compiler to complain about
    non-existent fields being assigned to.
    
    It seems like the compiler.h header that contains these redefinitions
    isn't actually needed in xf86x86emu.c, so the easiest "fix" is to not
    include it.
    
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Reviewed-by: Rob Clark <robdclark at gmail.com>

diff --git a/hw/xfree86/int10/xf86x86emu.c b/hw/xfree86/int10/xf86x86emu.c
index b9a4d36..4b0a130 100644
--- a/hw/xfree86/int10/xf86x86emu.c
+++ b/hw/xfree86/int10/xf86x86emu.c
@@ -9,7 +9,6 @@
 
 #include <x86emu.h>
 #include "xf86.h"
-#include "compiler.h"
 #include "xf86_OSproc.h"
 #include "xf86Pci.h"
 #define _INT10_PRIVATE
commit 774fea38c48671ed44e54278f0280bae04822491
Author: Rob Clark <robdclark at gmail.com>
Date:   Thu Apr 3 15:35:53 2014 -0400

    int10: fix build error
    
    Fixes:
    
      stub.c:66:1: error: conflicting types for 'xf86int10Addr'
      In file included from stub.c:14:0:
      xf86int10.h:72:53: note: previous declaration of 'xf86int10Addr' was here
    
    Signed-off-by: Rob Clark <robdclark at gmail.com>

diff --git a/hw/xfree86/int10/stub.c b/hw/xfree86/int10/stub.c
index 40e0ba7..4bbcdde 100644
--- a/hw/xfree86/int10/stub.c
+++ b/hw/xfree86/int10/stub.c
@@ -63,7 +63,7 @@ xf86ExecX86int10(xf86Int10InfoPtr pInt)
 }
 
 void *
-xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr)
+xf86int10Addr(xf86Int10InfoPtr pInt, uint32_t addr)
 {
     return 0;
 }
commit b241934238feedcb86c113fe3beb69a7470de02d
Author: Rob Clark <robdclark at gmail.com>
Date:   Thu Apr 3 14:54:02 2014 -0400

    default to stub int10 implementation on arm
    
    There should be no reason to need a real int10 implementation on arm,
    and switching to stub is an easy way to fix:
    
      xf86x86emu.c: In function 'xf86Int10ExecSetup':
      xf86x86emu.c:56:9: error: unknown field 'xf_outb' specified in initializer
      xf86x86emu.c:57:9: error: unknown field 'xf_outw' specified in initializer
      xf86x86emu.c:58:9: error: unknown field 'xf_outl' specified in initializer
    
    which is caused by the following in compiler.h:
    
      #define outb xf_outb
      #define outw xf_outw
      #define outl xf_outl
    
    Signed-off-by: Rob Clark <robdclark at gmail.com>
    Acked-by: Daniel Stone <daniels at collabora.com>

diff --git a/configure.ac b/configure.ac
index 0c8b516..e5387bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -325,6 +325,7 @@ case $host_cpu in
 	;;
   arm*)
 	ARM_VIDEO=yes
+	DEFAULT_INT10="stub"
 	;;
   i*86)
 	I386_VIDEO=yes
commit 4c3932620c29c91dfbbc8eb09c84efcaa7ec873e
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 25 08:22:15 2014 -0700

    hw/xfree86: Restore API compatibility for cursor loading functions
    
    Create load_cursor_image_check, load_cursor_argb_check,
    LoadCursorImageCheck and LoadCursorARGBCheck that can return failure
    and use them in preference to the old unchecked variants.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Michael Thayer <michael.thayer at oracle.com>

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 5407deb..eebe6f4 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -186,14 +186,18 @@ typedef struct _xf86CrtcFuncs {
     /**
      * Load monochrome image
      */
-    Bool
+    void
      (*load_cursor_image) (xf86CrtcPtr crtc, CARD8 *image);
+    Bool
+     (*load_cursor_image_check) (xf86CrtcPtr crtc, CARD8 *image);
 
     /**
      * Load ARGB image
      */
-    Bool
+    void
      (*load_cursor_argb) (xf86CrtcPtr crtc, CARD32 *image);
+    Bool
+     (*load_cursor_argb_check) (xf86CrtcPtr crtc, CARD32 *image);
 
     /**
      * Clean up driver-specific bits of the crtc
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 10ef6f6..379a27a 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -209,6 +209,40 @@ set_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
 }
 
 /*
+ * Wrappers to deal with API compatibility with drivers that don't expose
+ * load_cursor_*_check
+ */
+static inline Bool
+xf86_driver_has_load_cursor_image(xf86CrtcPtr crtc)
+{
+    return crtc->funcs->load_cursor_image_check || crtc->funcs->load_cursor_image;
+}
+
+static inline Bool
+xf86_driver_has_load_cursor_argb(xf86CrtcPtr crtc)
+{
+    return crtc->funcs->load_cursor_argb_check || crtc->funcs->load_cursor_argb;
+}
+
+static inline Bool
+xf86_driver_load_cursor_image(xf86CrtcPtr crtc, CARD8 *cursor_image)
+{
+    if (crtc->funcs->load_cursor_image_check)
+        return crtc->funcs->load_cursor_image_check(crtc, cursor_image);
+    crtc->funcs->load_cursor_image(crtc, cursor_image);
+    return TRUE;
+}
+
+static inline Bool
+xf86_driver_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *cursor_argb)
+{
+    if (crtc->funcs->load_cursor_argb_check)
+        return crtc->funcs->load_cursor_argb_check(crtc, cursor_argb);
+    crtc->funcs->load_cursor_argb(crtc, cursor_argb);
+    return TRUE;
+}
+
+/*
  * Load a two color cursor into a driver that supports only ARGB cursors
  */
 static Bool
@@ -244,7 +278,7 @@ xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src)
                 bits = 0;
             cursor_image[y * cursor_info->MaxWidth + x] = bits;
         }
-    return crtc->funcs->load_cursor_argb(crtc, cursor_image);
+    return xf86_driver_load_cursor_argb(crtc, cursor_image);
 }
 
 /*
@@ -269,7 +303,7 @@ xf86_set_cursor_colors(ScrnInfoPtr scrn, int bg, int fg)
         xf86CrtcPtr crtc = xf86_config->crtc[c];
 
         if (crtc->enabled && !crtc->cursor_argb) {
-            if (crtc->funcs->load_cursor_image)
+            if (xf86_driver_has_load_cursor_image(crtc))
                 crtc->funcs->set_cursor_colors(crtc, bg, fg);
             else if (bits)
                 xf86_crtc_convert_cursor_to_argb(crtc, bits);
@@ -450,7 +484,7 @@ xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src)
                     set_bit(cursor_image, cursor_info, x, y, TRUE);
             }
     }
-    return crtc->funcs->load_cursor_image(crtc, cursor_image);
+    return xf86_driver_load_cursor_image(crtc, cursor_image);
 }
 
 /*
@@ -466,10 +500,10 @@ xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
         xf86CrtcPtr crtc = xf86_config->crtc[c];
 
         if (crtc->enabled) {
-            if (crtc->funcs->load_cursor_image) {
+            if (xf86_driver_has_load_cursor_image(crtc)) {
                 if (!xf86_crtc_load_cursor_image(crtc, src))
                     return FALSE;
-            } else if (crtc->funcs->load_cursor_argb) {
+            } else if (xf86_driver_has_load_cursor_argb(crtc)) {
                 if (!xf86_crtc_convert_cursor_to_argb(crtc, src))
                     return FALSE;
             } else
@@ -549,7 +583,7 @@ xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor)
             cursor_image[y * image_width + x] = bits;
         }
 
-    return crtc->funcs->load_cursor_argb(crtc, cursor_image);
+    return xf86_driver_load_cursor_argb(crtc, cursor_image);
 }
 
 static Bool
@@ -594,14 +628,14 @@ xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags)
 
     cursor_info->SetCursorColors = xf86_set_cursor_colors;
     cursor_info->SetCursorPosition = xf86_set_cursor_position;
-    cursor_info->LoadCursorImage = xf86_load_cursor_image;
+    cursor_info->LoadCursorImageCheck = xf86_load_cursor_image;
     cursor_info->HideCursor = xf86_hide_cursors;
     cursor_info->ShowCursor = xf86_show_cursors;
     cursor_info->UseHWCursor = xf86_use_hw_cursor;
 #ifdef ARGB_CURSOR
     if (flags & HARDWARE_CURSOR_ARGB) {
         cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
-        cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
+        cursor_info->LoadCursorARGBCheck = xf86_load_cursor_argb;
     }
 #endif
 
@@ -658,11 +692,11 @@ xf86_reload_cursors(ScreenPtr screen)
             dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey,
                                    screen);
 #ifdef ARGB_CURSOR
-        if (cursor->bits->argb && cursor_info->LoadCursorARGB)
-            (*cursor_info->LoadCursorARGB) (scrn, cursor);
+        if (cursor->bits->argb && xf86DriverHasLoadCursorARGB(cursor_info))
+            xf86DriverLoadCursorARGB(cursor_info, cursor);
         else if (src)
 #endif
-            (*cursor_info->LoadCursorImage) (scrn, src);
+            xf86DriverLoadCursorImage(cursor_info, src);
 
         x += scrn->frameX0 + cursor_screen_priv->HotX;
         y += scrn->frameY0 + cursor_screen_priv->HotY;
diff --git a/hw/xfree86/ramdac/IBM.c b/hw/xfree86/ramdac/IBM.c
index 872d3d4..45876cf 100644
--- a/hw/xfree86/ramdac/IBM.c
+++ b/hw/xfree86/ramdac/IBM.c
@@ -622,7 +622,7 @@ IBMramdac526HWCursorInit(xf86CursorInfoPtr infoPtr)
         HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
     infoPtr->SetCursorColors = IBMramdac526SetCursorColors;
     infoPtr->SetCursorPosition = IBMramdac526SetCursorPosition;
-    infoPtr->LoadCursorImage = IBMramdac526LoadCursorImage;
+    infoPtr->LoadCursorImageCheck = IBMramdac526LoadCursorImage;
     infoPtr->HideCursor = IBMramdac526HideCursor;
     infoPtr->ShowCursor = IBMramdac526ShowCursor;
     infoPtr->UseHWCursor = IBMramdac526UseHWCursor;
@@ -638,7 +638,7 @@ IBMramdac640HWCursorInit(xf86CursorInfoPtr infoPtr)
         HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
     infoPtr->SetCursorColors = IBMramdac640SetCursorColors;
     infoPtr->SetCursorPosition = IBMramdac640SetCursorPosition;
-    infoPtr->LoadCursorImage = IBMramdac640LoadCursorImage;
+    infoPtr->LoadCursorImageCheck = IBMramdac640LoadCursorImage;
     infoPtr->HideCursor = IBMramdac640HideCursor;
     infoPtr->ShowCursor = IBMramdac640ShowCursor;
     infoPtr->UseHWCursor = IBMramdac640UseHWCursor;
diff --git a/hw/xfree86/ramdac/TI.c b/hw/xfree86/ramdac/TI.c
index 7d4e0d7..2492bb5 100644
--- a/hw/xfree86/ramdac/TI.c
+++ b/hw/xfree86/ramdac/TI.c
@@ -676,7 +676,7 @@ TIramdacHWCursorInit(xf86CursorInfoPtr infoPtr)
         HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
     infoPtr->SetCursorColors = TIramdacSetCursorColors;
     infoPtr->SetCursorPosition = TIramdacSetCursorPosition;
-    infoPtr->LoadCursorImage = TIramdacLoadCursorImage;
+    infoPtr->LoadCursorImageCheck = TIramdacLoadCursorImage;
     infoPtr->HideCursor = TIramdacHideCursor;
     infoPtr->ShowCursor = TIramdacShowCursor;
     infoPtr->UseHWCursor = TIramdacUseHWCursor;
diff --git a/hw/xfree86/ramdac/xf86Cursor.h b/hw/xfree86/ramdac/xf86Cursor.h
index 1ecbdcd..a389a99 100644
--- a/hw/xfree86/ramdac/xf86Cursor.h
+++ b/hw/xfree86/ramdac/xf86Cursor.h
@@ -12,7 +12,8 @@ typedef struct _xf86CursorInfoRec {
     int MaxHeight;
     void (*SetCursorColors) (ScrnInfoPtr pScrn, int bg, int fg);
     void (*SetCursorPosition) (ScrnInfoPtr pScrn, int x, int y);
-    Bool (*LoadCursorImage) (ScrnInfoPtr pScrn, unsigned char *bits);
+    void (*LoadCursorImage) (ScrnInfoPtr pScrn, unsigned char *bits);
+    Bool (*LoadCursorImageCheck) (ScrnInfoPtr pScrn, unsigned char *bits);
     void (*HideCursor) (ScrnInfoPtr pScrn);
     void (*ShowCursor) (ScrnInfoPtr pScrn);
     unsigned char *(*RealizeCursor) (struct _xf86CursorInfoRec *, CursorPtr);
@@ -20,11 +21,42 @@ typedef struct _xf86CursorInfoRec {
 
 #ifdef ARGB_CURSOR
     Bool (*UseHWCursorARGB) (ScreenPtr, CursorPtr);
-    Bool (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr);
+    void (*LoadCursorARGB) (ScrnInfoPtr, CursorPtr);
+    Bool (*LoadCursorARGBCheck) (ScrnInfoPtr, CursorPtr);
 #endif
 
 } xf86CursorInfoRec, *xf86CursorInfoPtr;
 
+static inline Bool
+xf86DriverHasLoadCursorImage(xf86CursorInfoPtr infoPtr)
+{
+    return infoPtr->LoadCursorImageCheck || infoPtr->LoadCursorImage;
+}
+
+static inline Bool
+xf86DriverLoadCursorImage(xf86CursorInfoPtr infoPtr, unsigned char *bits)
+{
+    if(infoPtr->LoadCursorImageCheck)
+        return infoPtr->LoadCursorImageCheck(infoPtr->pScrn, bits);
+    infoPtr->LoadCursorImage(infoPtr->pScrn, bits);
+    return TRUE;
+}
+
+static inline Bool
+xf86DriverHasLoadCursorARGB(xf86CursorInfoPtr infoPtr)
+{
+    return infoPtr->LoadCursorARGBCheck || infoPtr->LoadCursorARGB;
+}
+
+static inline Bool
+xf86DriverLoadCursorARGB(xf86CursorInfoPtr infoPtr, CursorPtr pCursor)
+{
+    if(infoPtr->LoadCursorARGBCheck)
+        return infoPtr->LoadCursorARGBCheck(infoPtr->pScrn, pCursor);
+    infoPtr->LoadCursorARGB(infoPtr->pScrn, pCursor);
+    return TRUE;
+}
+
 extern _X_EXPORT Bool xf86InitCursor(ScreenPtr pScreen,
                                      xf86CursorInfoPtr infoPtr);
 extern _X_EXPORT xf86CursorInfoPtr xf86CreateCursorInfoRec(void);
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index 0b5caa2..953c86a 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -87,7 +87,7 @@ xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
 
     /* These are required for now */
     if (!infoPtr->SetCursorPosition ||
-        !infoPtr->LoadCursorImage ||
+        !xf86DriverHasLoadCursorImage(infoPtr) ||
         !infoPtr->HideCursor ||
         !infoPtr->ShowCursor || !infoPtr->SetCursorColors)
         return FALSE;
@@ -140,7 +140,7 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
     y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY;
 
 #ifdef ARGB_CURSOR
-    if (!pCurs->bits->argb || !infoPtr->LoadCursorARGB)
+    if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
 #endif
         if (!bits) {
             bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
@@ -152,13 +152,13 @@ xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
         (*infoPtr->HideCursor) (infoPtr->pScrn);
 
 #ifdef ARGB_CURSOR
-    if (pCurs->bits->argb && infoPtr->LoadCursorARGB) {
-        if (!(*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs))
+    if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
+        if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
             return FALSE;
     } else
 #endif
     if (bits)
-        if (!(*infoPtr->LoadCursorImage) (infoPtr->pScrn, bits))
+        if (!xf86DriverLoadCursorImage (infoPtr, bits))
             return FALSE;
 
     xf86RecolorCursor(pScreen, pCurs, 1);
@@ -185,8 +185,8 @@ xf86SetTransparentCursor(ScreenPtr pScreen)
         (*infoPtr->HideCursor) (infoPtr->pScrn);
 
     if (ScreenPriv->transparentData)
-        (*infoPtr->LoadCursorImage) (infoPtr->pScrn,
-                                     ScreenPriv->transparentData);
+        xf86DriverLoadCursorImage (infoPtr,
+                                   ScreenPriv->transparentData);
 
     (*infoPtr->ShowCursor) (infoPtr->pScrn);
 }
commit 99f0365b1fbdfd9238b9f5cc28491e4e6c7324f1
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 23 09:52:17 2014 -0700

    Add a command line argument for disabling indirect GLX.
    
    The attack surface for indirect GLX is huge, and it's of no use to
    most people (if you get an indirect GL context, you're better served
    by a immediate X error than actually trying to use an indirect GL
    context and finding out that it doesn't support doing anything you
    want, slowly).  This flag gives you a chance to disable indirect GLX
    in environments where you just don't need it.
    
    I put in both the '+' and '-' arguments right now, so that it's easy
    to patch the value to change the default policy.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Acked-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index fb236b6..2fc3f4c 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -275,6 +275,17 @@ DoCreateContext(__GLXclientState * cl, GLXContextID gcId,
      ** Allocate memory for the new context
      */
     if (!isDirect) {
+        /* Only allow creating indirect GLX contexts if allowed by
+         * server command line.  Indirect GLX is of limited use (since
+         * it's only GL 1.4), it's slower than direct contexts, and
+         * it's a massive attack surface for buffer overflow type
+         * errors.
+         */
+        if (!enableIndirectGLX) {
+            client->errorValue = isDirect;
+            return BadValue;
+        }
+
         /* Without any attributes, the only error that the driver should be
          * able to generate is BadAlloc.  As result, just drop the error
          * returned from the driver on the floor.
diff --git a/include/opaque.h b/include/opaque.h
index 6b8071c..a2c54aa 100644
--- a/include/opaque.h
+++ b/include/opaque.h
@@ -56,6 +56,7 @@ extern _X_EXPORT Bool explicit_display;
 extern _X_EXPORT int defaultBackingStore;
 extern _X_EXPORT Bool disableBackingStore;
 extern _X_EXPORT Bool enableBackingStore;
+extern _X_EXPORT Bool enableIndirectGLX;
 extern _X_EXPORT Bool PartialNetwork;
 extern _X_EXPORT Bool RunFromSigStopParent;
 
diff --git a/os/utils.c b/os/utils.c
index 83d85cd..bc5e7df 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -194,6 +194,8 @@ Bool noGEExtension = FALSE;
 
 Bool CoreDump;
 
+Bool enableIndirectGLX = TRUE;
+
 #ifdef PANORAMIX
 Bool PanoramiXExtensionDisabledHack = FALSE;
 #endif
@@ -538,6 +540,8 @@ UseMsg(void)
     ErrorF("-fn string             default font name\n");
     ErrorF("-fp string             default font path\n");
     ErrorF("-help                  prints message with these options\n");
+    ErrorF("+iglx                  Allow creating indirect GLX contexts (default)\n");
+    ErrorF("-iglx                  Prohibit creating indirect GLX contexts\n");
     ErrorF("-I                     ignore all remaining arguments\n");
 #ifdef RLIMIT_DATA
     ErrorF("-ld int                limit data space to N Kb\n");
@@ -784,6 +788,10 @@ ProcessCommandLine(int argc, char *argv[])
             UseMsg();
             exit(0);
         }
+        else if (strcmp(argv[i], "+iglx") == 0)
+            enableIndirectGLX = TRUE;
+        else if (strcmp(argv[i], "-iglx") == 0)
+            enableIndirectGLX = FALSE;
         else if ((skip = XkbProcessArguments(argc, argv, i)) != 0) {
             if (skip > 0)
                 i += skip - 1;
commit a4d96afdbddb7a636df8e336059d3a5624f2e6ae
Author: Zhigang Gong <zhigang.gong at intel.com>
Date:   Wed Apr 23 18:54:43 2014 +0900

    glamor: Fallback to system memory when fail to allocate one big fbo.
    
    Even when create a pixmap which smaller than the max_fbo_size,
    it may fail due to some low level driver limitation. If that is
    the case, we don't need to crash the xserver. We just need to
    fallback to system memory.
    
    See the related bug at:
    https://bugs.freedesktop.org/show_bug.cgi?id=71190
    
    Signed-off-by: Zhigang Gong <zhigang.gong at intel.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Tested-by: Kai Wasserbach <kai at dev.carbon-project.org>
    Tested-by: Erich Seifert <eseifert at error-reports.org>
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 994e923..08f6ba1 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -146,7 +146,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
     glamor_pixmap_type_t type = GLAMOR_TEXTURE_ONLY;
     glamor_pixmap_private *pixmap_priv;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_pixmap_fbo *fbo;
+    glamor_pixmap_fbo *fbo = NULL;
     int pitch;
     GLenum format;
 
@@ -199,13 +199,12 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
         pixmap_priv->base.box.x2 = w;
         pixmap_priv->base.box.y2 = h;
         fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
-    }
-    else {
-        DEBUGF("Create LARGE pixmap %p width %d height %d\n", pixmap, w, h);
+    } else {
+        int tile_size = glamor_priv->max_fbo_size;
+        DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n", pixmap, w, h, tile_size);
         pixmap_priv->type = GLAMOR_TEXTURE_LARGE;
         fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage,
-                                      glamor_priv->max_fbo_size,
-                                      glamor_priv->max_fbo_size, pixmap_priv);
+                                      tile_size, tile_size, pixmap_priv);
     }
 
     if (fbo == NULL) {
@@ -658,7 +657,8 @@ glamor_fd_from_pixmap(ScreenPtr screen,
     switch (pixmap_priv->type) {
     case GLAMOR_TEXTURE_DRM:
     case GLAMOR_TEXTURE_ONLY:
-        glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0);
+        if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0))
+            return -1;
         return glamor_egl_dri3_fd_name_from_tex(screen,
                                                 pixmap,
                                                 pixmap_priv->base.fbo->tex,
@@ -682,7 +682,8 @@ glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
     switch (pixmap_priv->type) {
     case GLAMOR_TEXTURE_DRM:
     case GLAMOR_TEXTURE_ONLY:
-        glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0);
+        if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0))
+            return -1;
         return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen,
                                                 pixmap,
                                                 pixmap_priv->base.fbo->tex,
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index ed4e348..5521683 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -174,10 +174,10 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
 #endif
 }
 
-static void
+static int
 glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
 {
-    int status;
+    int status, err = 0;
 
     glamor_make_current(fbo->glamor_priv);
 
@@ -215,9 +215,11 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
             break;
         }
 
-        FatalError("destination is framebuffer incomplete: %s [%x]\n",
-                   str, status);
+        glamor_fallback("glamor: Failed to create fbo, %s\n", str);
+        err = -1;
     }
+
+    return err;
 }
 
 glamor_pixmap_fbo *
@@ -244,8 +246,12 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
         goto done;
     }
 
-    if (flag != GLAMOR_CREATE_FBO_NO_FBO)
-        glamor_pixmap_ensure_fb(fbo);
+    if (flag != GLAMOR_CREATE_FBO_NO_FBO) {
+        if (glamor_pixmap_ensure_fb(fbo) != 0) {
+            glamor_purge_fbo(fbo);
+            fbo = NULL;
+        }
+    }
 
  done:
     return fbo;
@@ -562,7 +568,8 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
                                    pixmap->drawable.height, format);
 
         if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->base.fbo->fb == 0)
-            glamor_pixmap_ensure_fb(pixmap_priv->base.fbo);
+            if (glamor_pixmap_ensure_fb(pixmap_priv->base.fbo) != 0)
+                return FALSE;
     }
 
     return TRUE;
commit 21e0e373858bd7f3458172ebd465397e33b90162
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Apr 23 18:54:42 2014 +0900

    glamor: Fix memory leak in _glamor_copy_n_to_n()
    
    It would leak the memory allocated for the region rects in some cases.
    Found with valgrind.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
    Reviewed-by: Zhigang Gong <zhigang.gong at linux.intel.com>
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 6e90e36..e198822 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -367,7 +367,7 @@ _glamor_copy_n_to_n(DrawablePtr src,
             goto fall_back;
         glamor_make_current(glamor_priv);
         if (!glamor_set_alu(screen, gc->alu)) {
-            goto fail;
+            goto fail_noregion;
         }
     }
 
@@ -533,7 +533,6 @@ _glamor_copy_n_to_n(DrawablePtr src,
         if (n_dst_region == 0)
             ok = TRUE;
         free(clipped_dst_regions);
-        RegionUninit(&region);
     }
     else {
         ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy,
@@ -541,6 +540,8 @@ _glamor_copy_n_to_n(DrawablePtr src,
     }
 
  fail:
+    RegionUninit(&region);
+ fail_noregion:
     glamor_make_current(glamor_priv);
     glamor_set_alu(screen, GXcopy);
 
commit 4e9aabb6fc15d8052934f20c6a07801c197ec36a
Author: Anthony Waters <awaters1 at gmail.com>
Date:   Wed Apr 23 18:54:41 2014 +0900

    glamor: Fix coordinates handling for composite source/mask pictures
    
    There were actually two issues with the original code I believe, the
    first is that the call to glamor_convert_gradient_picture wasn't
    properly referencing the coordinates of the source/mask pictures.  The
    second, was that the updated references (x_temp/y_temp) were also
    improperly set, they should always be 0 because the temp pictures are
    new ones that start at (0, 0).  The reason it worked in certain cases
    and it didn't in others (notably the tray icons) was due to the
    numbers working out based on the call to glamor_composite.  In the
    cases that it did work extent->x1 would equal x_dest and extent->y1
    would equal y_dest, making it so what was actually passed into
    glamor_convert_gradient_picture and the settings for x_temp/y_temp
    were correct.  However, for the case when extent->x1 wouldn't equal
    x_dest and extent->y1 wouldn't equal y_dest (for example with the tray
    icons) then the wrong parameters get passed into
    glamor_convert_gradient_picture and x_temp/y_temp are set improperly.
    
    Fixes issues with tray icons not appearing properly in certain cases.
    
    Bug:
    https://bugs.freedesktop.org/show_bug.cgi?id=64738
    
    Signed-Off-by: Anthony Waters <awaters1 at gmail.com>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
    Reviewed-by: Zhigang Gong <zhigang.gong at linux.intel.com>
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 14ab738..5a7a238 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1450,8 +1450,8 @@ glamor_composite_clipped_region(CARD8 op,
                     || source_pixmap->drawable.height != height)))) {
         temp_src =
             glamor_convert_gradient_picture(screen, source,
-                                            extent->x1 + x_source - x_dest,
-                                            extent->y1 + y_source - y_dest,
+                                            x_source,
+                                            y_source,
                                             width, height);
         if (!temp_src) {
             temp_src = source;
@@ -1459,8 +1459,8 @@ glamor_composite_clipped_region(CARD8 op,
         }
         temp_src_priv =
             glamor_get_pixmap_private((PixmapPtr) (temp_src->pDrawable));
-        x_temp_src = -extent->x1 + x_dest;
-        y_temp_src = -extent->y1 + y_dest;
+        x_temp_src = 0;
+        y_temp_src = 0;
     }
 
     if (mask
@@ -1474,8 +1474,8 @@ glamor_composite_clipped_region(CARD8 op,
          * to do reduce one convertion. */
         temp_mask =
             glamor_convert_gradient_picture(screen, mask,
-                                            extent->x1 + x_mask - x_dest,
-                                            extent->y1 + y_mask - y_dest,
+                                            x_mask,
+                                            y_mask,
                                             width, height);
         if (!temp_mask) {
             temp_mask = mask;
@@ -1483,8 +1483,8 @@ glamor_composite_clipped_region(CARD8 op,
         }
         temp_mask_priv =
             glamor_get_pixmap_private((PixmapPtr) (temp_mask->pDrawable));
-        x_temp_mask = -extent->x1 + x_dest;
-        y_temp_mask = -extent->y1 + y_dest;
+        x_temp_mask = 0;
+        y_temp_mask = 0;
     }
     /* Do two-pass PictOpOver componentAlpha, until we enable
      * dual source color blending.
commit 5062b4fadd977d044e54b53b7f3e02e466eac9a9
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Mar 16 20:44:48 2014 -0700

    glamor: Add glamor_transfer based glamor_get_image and glamor_put_image
    
    These use the upload_boxes and download_boxes helpers to provide
    reasonably efficient image transfer.
    
    Fixes segfaults in Xephyr with x11perf -reps 1.
    
    Performance improvements:
    
    Improves -putimage10 by 548.218% +/- 88.601% (n=10).
    Improves -putimage500 by 3.71014% +/- 1.5049% (n=10).
    Improves -getimage10 by 8.37004% +/- 4.58274% (n=10).
    No statistically significant difference on -getimage500 (n=10).
    
    v2: Fix rebase failures, don't forget to check/prepare the gc in
        putimage fallbacks (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 b7069e0..bde58b6 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -17,8 +17,8 @@ libglamor_la_SOURCES = \
 	glamor_glx.c \
 	glamor_glyphs.c \
 	glamor_polylines.c \
-	glamor_putimage.c \
 	glamor_segment.c \
+	glamor_image.c \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_program.c \
@@ -34,7 +34,6 @@ libglamor_la_SOURCES = \
 	glamor_tile.c \
 	glamor_triangles.c\
 	glamor_addtraps.c\
-	glamor_getimage.c\
 	glamor_copyplane.c\
 	glamor_glyphblt.c\
 	glamor_points.c\
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 29f8874..994e923 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -507,7 +507,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 #ifdef GLAMOR_TRAPEZOID_SHADER
     glamor_init_trapezoid_shader(screen);
 #endif
-    glamor_init_putimage_shaders(screen);
     glamor_init_finish_access_shaders(screen);
 #ifdef GLAMOR_GRADIENT_SHADER
     glamor_init_gradient_shader(screen);
@@ -541,7 +540,6 @@ glamor_release_screen_priv(ScreenPtr screen)
 #ifdef GLAMOR_TRAPEZOID_SHADER
     glamor_fini_trapezoid_shader(screen);
 #endif
-    glamor_fini_putimage_shaders(screen);
     glamor_fini_finish_access_shaders(screen);
 #ifdef GLAMOR_GRADIENT_SHADER
     glamor_fini_gradient_shader(screen);
diff --git a/glamor/glamor_getimage.c b/glamor/glamor_getimage.c
deleted file mode 100644
index a932473..0000000
--- a/glamor/glamor_getimage.c
+++ /dev/null
@@ -1,96 +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"
-
-static Bool
-_glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
-                  unsigned int format, unsigned long planeMask, char *d,
-                  Bool fallback)
-{
-    PixmapPtr pixmap, sub_pixmap;
-    struct glamor_pixmap_private *pixmap_priv;
-    int x_off, y_off;
-    int stride;
-    void *data;
-
-    pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off);
-
-    if (format != ZPixmap)
-        goto fall_back;
-
-    if (!glamor_set_planemask(pixmap, planeMask)) {
-        glamor_fallback("Failedto set planemask  in glamor_solid.\n");
-        goto fall_back;
-    }
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        goto fall_back;
-    stride = PixmapBytePad(w, drawable->depth);
-
-    x += drawable->x + x_off;
-    y += drawable->y + y_off;
-
-    data = glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h, stride,
-                                             d, 0, GLAMOR_ACCESS_RO);
-    if (data != NULL) {
-        assert(data == d);
-        return TRUE;
-    }
- fall_back:
-    sub_pixmap = glamor_get_sub_pixmap(pixmap, x + x_off + drawable->x,
-                                       y + y_off + drawable->y, w, h,
-                                       GLAMOR_ACCESS_RO);
-    if (sub_pixmap) {
-        fbGetImage(&sub_pixmap->drawable, 0, 0, w, h, format, planeMask, d);
-        glamor_put_sub_pixmap(sub_pixmap, pixmap,
-                              x + x_off + drawable->x,
-                              y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RO);
-    }
-    else
-        miGetImage(drawable, x, y, w, h, format, planeMask, d);
-
-    return TRUE;
-}
-
-void
-glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
-                 unsigned int format, unsigned long planeMask, char *d)
-{
-    _glamor_get_image(pDrawable, x, y, w, h, format, planeMask, d, TRUE);
-}
-
-Bool
-glamor_get_image_nf(DrawablePtr pDrawable, int x, int y, int w, int h,
-                    unsigned int format, unsigned long planeMask, char *d)
-{
-    return _glamor_get_image(pDrawable, x, y, w,
-                             h, format, planeMask, d, FALSE);
-}
diff --git a/glamor/glamor_image.c b/glamor/glamor_image.c
new file mode 100644
index 0000000..4791d08
--- /dev/null
+++ b/glamor/glamor_image.c
@@ -0,0 +1,180 @@
+/*
+ * 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"
+#include "glamor_transform.h"
+
+/*
+ * PutImage. Only does ZPixmap right now as other formats are quite a bit harder
+ */
+
+static Bool
+glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+                    int w, int h, int leftPad, int format, char *bits)
+{
+    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;
+    uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
+    RegionRec   region;
+    BoxRec      box;
+    int         off_x, off_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        return FALSE;
+
+    if (gc->alu != GXcopy)
+        goto bail;
+
+    if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask))
+        goto bail;
+
+    if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
+        format = ZPixmap;
+
+    if (format != ZPixmap)
+        goto bail;
+
+    x += drawable->x;
+    y += drawable->y;
+    box.x1 = x;
+    box.y1 = y;
+    box.x2 = box.x1 + w;
+    box.y2 = box.y1 + h;
+    RegionInit(&region, &box, 1);
+    RegionIntersect(&region, &region, gc->pCompositeClip);
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+    if (off_x || off_y) {
+        x += off_x;
+        y += off_y;
+        RegionTranslate(&region, off_x, off_y);
+    }
+
+    glamor_make_current(glamor_priv);
+
+    glamor_upload_region(pixmap, &region, x, y, (uint8_t *) bits, byte_stride);
+
+    RegionUninit(&region);
+    return TRUE;
+bail:
+    return FALSE;
+}
+
+static void
+glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+                      int w, int h, int leftPad, int format, char *bits)
+{
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+        glamor_prepare_access_gc(gc))
+        fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
+    glamor_finish_access(drawable);
+}
+
+void
+glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+                 int w, int h, int leftPad, int format, char *bits)
+{
+    if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
+        return;
+    glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
+}
+
+Bool
+glamor_put_image_nf(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+                    int w, int h, int leftPad, int format, char *bits)
+{
+    if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
+        return TRUE;
+    if (glamor_ddx_fallback_check_pixmap(drawable) &&
+        glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+    glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
+    return TRUE;
+}
+
+static Bool
+glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
+                    unsigned int format, unsigned long plane_mask, char *d)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
+    BoxRec      box;
+    int         off_x, off_y;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    if (format != ZPixmap || !glamor_pm_is_solid(drawable, plane_mask))
+        goto bail;
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+    box.x1 = x;
+    box.x2 = x + w;
+    box.y1 = y;
+    box.y2 = y + h;
+    glamor_download_boxes(pixmap, &box, 1,
+                          drawable->x + off_x, drawable->y + off_y,
+                          -x, -y,
+                          (uint8_t *) d, byte_stride);
+    return TRUE;
+bail:
+    return FALSE;
+}
+
+static void
+glamor_get_image_bail(DrawablePtr drawable, int x, int y, int w, int h,
+                      unsigned int format, unsigned long plane_mask, char *d)
+{
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO))
+        fbGetImage(drawable, x, y, w, h, format, plane_mask, d);
+    glamor_finish_access(drawable);
+}
+
+void
+glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
+                 unsigned int format, unsigned long plane_mask, char *d)
+{
+    if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d))
+        return;
+    glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d);
+}
+
+Bool
+glamor_get_image_nf(DrawablePtr drawable, int x, int y, int w, int h,
+                    unsigned int format, unsigned long plane_mask, char *d)
+{
+    if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable))
+        return FALSE;
+
+    glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d);
+    return TRUE;
+}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 0cafac4..a2a21fc 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -277,11 +277,6 @@ typedef struct glamor_screen_private {
     /* glamor trapezoid shader. */
     GLint trapezoid_prog;
 
-    /* glamor_putimage */
-    GLint put_image_xybitmap_prog;
-    GLint put_image_xybitmap_fg_uniform_location;
-    GLint put_image_xybitmap_bg_uniform_location;
-
     PixmapPtr *back_pixmap;
     int screen_fbo;
     struct glamor_saved_procs saved_procs;
@@ -704,12 +699,6 @@ void glamor_glyphs(CARD8 op,
 void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
                        DDXPointPtr points);
 
-/* glamor_putimage.c */
-void glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
-                      int w, int h, int leftPad, int format, char *bits);
-void glamor_init_putimage_shaders(ScreenPtr screen);
-void glamor_fini_putimage_shaders(ScreenPtr screen);
-
 /* glamor_render.c */
 Bool glamor_composite_clipped_region(CARD8 op,
                                      PicturePtr source,
@@ -951,9 +940,6 @@ Bool glamor_fixup_pixmap_priv(ScreenPtr screen,
 void glamor_picture_format_fixup(PicturePtr picture,
                                  glamor_pixmap_private *pixmap_priv);
 
-void glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
-                      unsigned int format, unsigned long planeMask, char *d);
-
 void glamor_add_traps(PicturePtr pPicture,
                       INT16 x_off, INT16 y_off, int ntrap, xTrap *traps);
 
@@ -994,6 +980,15 @@ void
 glamor_poly_fill_rect(DrawablePtr drawable,
                       GCPtr gc, int nrect, xRectangle *prect);
 
+/* glamor_image.c */
+void
+glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+                 int w, int h, int leftPad, int format, char *bits);
+
+void
+glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
+                 unsigned int format, unsigned long planeMask, char *d);
+
 /* glamor_glyphblt.c */
 void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
                             int x, int y, unsigned int nglyph,
diff --git a/glamor/glamor_putimage.c b/glamor/glamor_putimage.c
deleted file mode 100644
index cf7197b..0000000
--- a/glamor/glamor_putimage.c
+++ /dev/null
@@ -1,161 +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>
- *
- */
-
-/** @file glamor_putaimge.c
- *
- * XPutImage implementation
- */
-#include "glamor_priv.h"
-
-void
-glamor_init_putimage_shaders(ScreenPtr screen)
-{
-}
-
-void
-glamor_fini_putimage_shaders(ScreenPtr screen)
-{
-}
-
-static Bool
-_glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
-                  int w, int h, int left_pad, int image_format, char *bits,
-                  Bool fallback)
-{
-    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    RegionPtr clip;
-    int x_off, y_off;
-    Bool ret = FALSE;
-    PixmapPtr temp_pixmap, sub_pixmap;
-    glamor_pixmap_private *temp_pixmap_priv;
-    BoxRec box;
-
-    glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off);
-    clip = fbGetCompositeClip(gc);
-    if (image_format == XYBitmap) {
-        assert(depth == 1);
-        goto fail;
-    }
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
-        glamor_fallback("has no fbo.\n");
-        goto fail;
-    }
-
-    if (image_format != ZPixmap) {
-        glamor_fallback("non-ZPixmap\n");
-        goto fail;
-    }
-
-    if (!glamor_set_planemask(pixmap, gc->planemask)) {
-        goto fail;
-    }
-    /* create a temporary pixmap and upload the bits to that
-     * pixmap, then apply clip copy it to the destination pixmap.*/
-    box.x1 = x + drawable->x;
-    box.y1 = y + drawable->y;
-    box.x2 = x + w + drawable->x;
-    box.y2 = y + h + drawable->y;
-
-    if ((clip != NULL && RegionContainsRect(clip, &box) != rgnIN)
-        || gc->alu != GXcopy) {
-        temp_pixmap = glamor_create_pixmap(drawable->pScreen, w, h, depth, 0);
-        if (temp_pixmap == NULL)
-            goto fail;
-
-        temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap);
-
-        if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv)) {
-            temp_pixmap_priv->base.picture = pixmap_priv->base.picture;
-            temp_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
-        }
-
-        glamor_upload_sub_pixmap_to_texture(temp_pixmap, 0, 0, w, h,
-                                            pixmap->devKind, bits, 0);
-
-        glamor_copy_area(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x,
-                         y);
-        glamor_destroy_pixmap(temp_pixmap);
-    }
-    else
-        glamor_upload_sub_pixmap_to_texture(pixmap, x + drawable->x + x_off,
-                                            y + drawable->y + y_off, w, h,
-                                            PixmapBytePad(w, depth), bits, 0);
-    ret = TRUE;
-    goto done;
-
- fail:
-    glamor_set_planemask(pixmap, ~0);
-
-    if (!fallback && glamor_ddx_fallback_check_pixmap(&pixmap->drawable))
-        goto done;
-
-    glamor_fallback("to %p (%c)\n",
-                    drawable, glamor_get_drawable_location(drawable));
-
-    sub_pixmap = glamor_get_sub_pixmap(pixmap, x + x_off + drawable->x,
-                                       y + y_off + drawable->y, w, h,
-                                       GLAMOR_ACCESS_RW);
-    if (sub_pixmap) {
-        if (clip != NULL)
-            pixman_region_translate(clip, -x - drawable->x, -y - drawable->y);
-
-        fbPutImage(&sub_pixmap->drawable, gc, depth, 0, 0, w, h,
-                   left_pad, image_format, bits);
-
-        glamor_put_sub_pixmap(sub_pixmap, pixmap,
-                              x + x_off + drawable->x,
-                              y + y_off + drawable->y, w, h, GLAMOR_ACCESS_RW);
-        if (clip != NULL)
-            pixman_region_translate(clip, x + drawable->x, y + drawable->y);
-    }
-    else
-        fbPutImage(drawable, gc, depth, x, y, w, h,
-                   left_pad, image_format, bits);
-    ret = TRUE;
-
- done:
-    return ret;
-}
-
-void
-glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
-                 int w, int h, int left_pad, int image_format, char *bits)
-{
-    _glamor_put_image(drawable, gc, depth, x, y, w, h,
-                      left_pad, image_format, bits, TRUE);
-}
-
-Bool
-glamor_put_image_nf(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
-                    int w, int h, int left_pad, int image_format, char *bits)
-{
-    return _glamor_put_image(drawable, gc, depth, x, y, w, h,
-                             left_pad, image_format, bits, FALSE);
-}
commit 747160016ba2d0cd42ad6b174cbf927d67c01875
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 22 16:33:45 2014 -0700

    glamor: Wire alpha to 1 for pictures without alpha bits
    
    When sourcing a picture that has no alpha values, make sure any
    texture fetches wire the alpha value to one. This ensures that bits
    beyond the depth of the pixmap, or bits other than the RGB values
    aren't used.
    
    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_render.c b/glamor/glamor_render.c
index 294a4ae..14ab738 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -870,7 +870,10 @@ glamor_composite_choose_shader(CARD8 op,
             goto fail;
     }
     else {
-        key.source = SHADER_SOURCE_TEXTURE_ALPHA;
+        if (PICT_FORMAT_A(source->format))
+            key.source = SHADER_SOURCE_TEXTURE_ALPHA;
+        else
+            key.source = SHADER_SOURCE_TEXTURE;
     }
 
     if (mask) {
commit a69907288d59792fd783f2f1756cde03d4a06f97
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Apr 21 17:47:15 2014 +0900

    glx: If DRI2GetBuffers changes the GL context, call it again
    
    By changing the context, it may also invalidate the DRI2 buffer
    information, so we need to get that again.
    
    Fixes crashes due to use-after-free with LIBGL_ALWAYS_INDIRECT=1
    glxgears and piglit.
    
    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>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 7b368d2..c756bf5 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -676,6 +676,13 @@ dri2GetBuffers(__DRIdrawable * driDrawable,
     if (cx != lastGLContext) {
         lastGLContext = cx;
         cx->makeCurrent(cx);
+
+        /* If DRI2GetBuffers() changed the GL context, it may also have
+         * invalidated the DRI2 buffers, so let's get them again
+         */
+        buffers = DRI2GetBuffers(private->base.pDraw,
+                                 width, height, attachments, count, out_count);
+        assert(lastGLContext == cx);
     }
 
     if (*out_count > MAX_DRAWABLE_BUFFERS) {
@@ -727,6 +734,14 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
     if (cx != lastGLContext) {
         lastGLContext = cx;
         cx->makeCurrent(cx);
+
+        /* If DRI2GetBuffersWithFormat() changed the GL context, it may also have
+         * invalidated the DRI2 buffers, so let's get them again
+         */
+        buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
+                                           width, height, attachments, count,
+                                           out_count);
+        assert(lastGLContext == cx);
     }
 
     if (*out_count > MAX_DRAWABLE_BUFFERS) {
commit f6abfece3e59fa8c2e14a61430133816837855f8
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Apr 17 18:50:13 2014 -0700

    glamor: Move a make_current before the first GL call entrypoint.
    
    Fixes a usage of the wrong context with swrast GLX's GetImage entrypoint.
    
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 371e486..54b414b 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -1217,6 +1217,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         assert(0);
     }
 
+    glamor_make_current(glamor_priv);
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
     need_post_conversion = (revert > REVERT_NORMAL);
@@ -1249,7 +1250,6 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         fbo_y_off = 0;
     }
 
-    glamor_make_current(glamor_priv);
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
     if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
commit 707726b155a2a086d12e0a6abef7f1e59def5370
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Apr 4 07:03:46 2014 +0100

    glamor: Do the same MakeCurrent(None) for GLX as we do for EGL.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_glx.c b/glamor/glamor_glx.c
index db8e661..7107c7c 100644
--- a/glamor/glamor_glx.c
+++ b/glamor/glamor_glx.c
@@ -36,6 +36,14 @@
 static void
 glamor_glx_make_current(struct glamor_context *glamor_ctx)
 {
+    /* There's only a single global dispatch table in Mesa.  EGL, GLX,
+     * and AIGLX's direct dispatch table manipulation don't talk to
+     * each other.  We need to set the context to NULL first to avoid
+     * GLX's no-op context change fast path when switching back to
+     * GLX.
+     */
+    glXMakeCurrent(glamor_ctx->display, None, None);
+
     glXMakeCurrent(glamor_ctx->display, glamor_ctx->drawable_xid,
                    glamor_ctx->ctx);
 }
commit 482b06a95a0a2c9a58bc196eb3dd928d796853df
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Apr 4 07:03:31 2014 +0100

    glamor: Explain the weird EGL_NO_CONTEXT code.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 1755d23..54af275 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -97,8 +97,15 @@ glamor_egl_get_screen_private(ScrnInfoPtr scrn)
 static void
 glamor_egl_make_current(struct glamor_context *glamor_ctx)
 {
+    /* There's only a single global dispatch table in Mesa.  EGL, GLX,
+     * and AIGLX's direct dispatch table manipulation don't talk to
+     * each other.  We need to set the context to NULL first to avoid
+     * EGL's no-op context change fast path when switching back to
+     * EGL.
+     */
     eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
     if (!eglMakeCurrent(glamor_ctx->display,
                         EGL_NO_SURFACE, EGL_NO_SURFACE,
                         glamor_ctx->ctx)) {
commit fab0a4a4c9dad2275bb398d09632f4274b5e16f2
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 14 17:31:18 2014 -0700

    glamor: Replace glamor_get/put_context() with just glamor_make_current().
    
    Now that we have the DIX global state for the current context, we
    don't need to track nesting to try to reduce MakeCurrent overhead.
    
    v2: Fix a mistaken replacement of a put_context with make_current in
        glamor_fill_spans_gl() (caught by keithp).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com> (v1)
    Reviewed-by: Adam Jackson <ajax at redhat.com> (v1)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 2c2d976..29f8874 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -248,11 +248,10 @@ glamor_block_handler(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glamor_priv->tick++;
     glFlush();
     glamor_fbo_expire(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;
@@ -265,9 +264,8 @@ _glamor_block_handler(void *data, OSTimePtr timeout, void *last_select_mask)
 {
     glamor_screen_private *glamor_priv = data;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glFlush();
-    glamor_put_context(glamor_priv);
 }
 
 static void
diff --git a/glamor/glamor_context.h b/glamor/glamor_context.h
index 8781afc..47b87e6 100644
--- a/glamor/glamor_context.h
+++ b/glamor/glamor_context.h
@@ -43,14 +43,7 @@ struct glamor_context {
     /** 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);
+    void (*make_current)(struct glamor_context *glamor_ctx);
 };
 
 Bool glamor_glx_screen_init(struct glamor_context *glamor_ctx);
diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
index 996611c..6e90e36 100644
--- a/glamor/glamor_copyarea.c
+++ b/glamor/glamor_copyarea.c
@@ -70,7 +70,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_context(glamor_priv);
+    glamor_make_current(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);
@@ -112,7 +112,6 @@ glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
                               GL_COLOR_BUFFER_BIT, GL_NEAREST);
         }
     }
-    glamor_put_context(glamor_priv);
     glamor_priv->state = BLIT_STATE;
     return TRUE;
 }
@@ -155,7 +154,7 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
 
     glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@@ -206,7 +205,6 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     /* The source texture is bound to a fbo, we have to flush it here. */
-    glamor_put_context(glamor_priv);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
     return TRUE;
@@ -367,12 +365,10 @@ _glamor_copy_n_to_n(DrawablePtr src,
     if (gc) {
         if (!glamor_set_planemask(dst_pixmap, gc->planemask))
             goto fall_back;
-        glamor_get_context(glamor_priv);
+        glamor_make_current(glamor_priv);
         if (!glamor_set_alu(screen, gc->alu)) {
-            glamor_put_context(glamor_priv);
             goto fail;
         }
-        glamor_put_context(glamor_priv);
     }
 
     if (!src_pixmap_priv) {
@@ -545,9 +541,8 @@ _glamor_copy_n_to_n(DrawablePtr src,
     }
 
  fail:
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glamor_set_alu(screen, GXcopy);
-    glamor_put_context(glamor_priv);
 
     if (ok)
         return TRUE;
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 5b341d3..b349437 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -241,7 +241,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
     char *source;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glamor_priv->finish_access_prog[0] = glCreateProgram();
     glamor_priv->finish_access_prog[1] = glCreateProgram();
 
@@ -300,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);
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -309,10 +308,9 @@ glamor_fini_finish_access_shaders(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glDeleteProgram(glamor_priv->finish_access_prog[0]);
     glDeleteProgram(glamor_priv->finish_access_prog[1]);
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -341,11 +339,10 @@ glamor_finish_access(DrawablePtr drawable)
     if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
         assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
 
-        glamor_get_context(glamor_priv);
+        glamor_make_current(glamor_priv);
         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
         glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
-        glamor_put_context(glamor_priv);
 
         pixmap_priv->base.fbo->pbo_valid = FALSE;
         pixmap_priv->base.fbo->pbo = 0;
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index a16022b..1755d23 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -95,11 +95,8 @@ glamor_egl_get_screen_private(ScrnInfoPtr scrn)
 }
 
 static void
-glamor_egl_get_context(struct glamor_context *glamor_ctx)
+glamor_egl_make_current(struct glamor_context *glamor_ctx)
 {
-    if (glamor_ctx->get_count++)
-        return;
-
     eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
                    EGL_NO_SURFACE, EGL_NO_CONTEXT);
     if (!eglMakeCurrent(glamor_ctx->display,
@@ -109,12 +106,6 @@ glamor_egl_get_context(struct glamor_context *glamor_ctx)
     }
 }
 
-static void
-glamor_egl_put_context(struct glamor_context *glamor_ctx)
-{
-    --glamor_ctx->get_count;
-}
-
 static EGLImageKHR
 _glamor_egl_create_image(struct glamor_egl_screen_private *glamor_egl,
                          int width, int height, int stride, int name, int depth)
@@ -166,7 +157,7 @@ glamor_create_texture_from_image(ScreenPtr screen,
     struct glamor_screen_private *glamor_priv =
         glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glGenTextures(1, texture);
     glBindTexture(GL_TEXTURE_2D, *texture);
@@ -176,8 +167,6 @@ glamor_create_texture_from_image(ScreenPtr screen,
     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
     glBindTexture(GL_TEXTURE_2D, 0);
 
-    glamor_put_context(glamor_priv);
-
     return TRUE;
 }
 
@@ -290,7 +279,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     if (glamor_egl->has_gem) {
         if (!glamor_get_flink_name(glamor_egl->fd, handle, &name)) {
             xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -320,7 +309,6 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
     ret = TRUE;
 
  done:
-    glamor_put_context(glamor_priv);
     return ret;
 }
 
@@ -340,7 +328,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     image = eglCreateImageKHR(glamor_egl->display,
                               glamor_egl->context,
@@ -356,7 +344,6 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
     ret = TRUE;
 
  done:
-    glamor_put_context(glamor_priv);
     return ret;
 }
 
@@ -414,7 +401,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     glamor_egl = glamor_egl_get_screen_private(scrn);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     image = pixmap_priv->base.image;
     if (!image) {
@@ -449,7 +436,6 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 
     gbm_bo_destroy(bo);
  failure:
-    glamor_put_context(glamor_priv);
     return fd;
 #else
     return -1;
@@ -679,8 +665,7 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
     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;
+    glamor_ctx->make_current = glamor_egl_make_current;
 
     if (glamor_egl->dri3_capable) {
         /* Tell the core that we have the interfaces for import/export
diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index d0215be..ed4e348 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_context(fbo->glamor_priv);
+    glamor_make_current(fbo->glamor_priv);
 
     if (fbo->fb)
         glDeleteFramebuffers(1, &fbo->fb);
@@ -137,7 +137,6 @@ glamor_purge_fbo(glamor_pixmap_fbo *fbo)
         glDeleteTextures(1, &fbo->tex);
     if (fbo->pbo)
         glDeleteBuffers(1, &fbo->pbo);
-    glamor_put_context(fbo->glamor_priv);
 
     free(fbo);
 }
@@ -180,7 +179,7 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
 {
     int status;
 
-    glamor_get_context(fbo->glamor_priv);
+    glamor_make_current(fbo->glamor_priv);
 
     if (fbo->fb == 0)
         glGenFramebuffers(1, &fbo->fb);
@@ -219,7 +218,6 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
         FatalError("destination is framebuffer incomplete: %s [%x]\n",
                    str, status);
     }
-    glamor_put_context(fbo->glamor_priv);
 }
 
 glamor_pixmap_fbo *
@@ -241,9 +239,8 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
     fbo->glamor_priv = glamor_priv;
 
     if (flag == GLAMOR_CREATE_PIXMAP_MAP) {
-        glamor_get_context(glamor_priv);
+        glamor_make_current(glamor_priv);
         glGenBuffers(1, &fbo->pbo);
-        glamor_put_context(glamor_priv);
         goto done;
     }
 
@@ -341,14 +338,13 @@ _glamor_create_tex(glamor_screen_private *glamor_priv,
                                                        w, h);
     }
     if (!tex) {
-        glamor_get_context(glamor_priv);
+        glamor_make_current(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_context(glamor_priv);
     }
     return tex;
 }
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
index 2fa726e..073904d 100644
--- a/glamor/glamor_fill.c
+++ b/glamor/glamor_fill.c
@@ -156,7 +156,7 @@ glamor_init_solid_shader(ScreenPtr screen)
     GLint fs_prog, vs_prog;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(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);
@@ -169,7 +169,6 @@ glamor_init_solid_shader(ScreenPtr screen)
 
     glamor_priv->solid_color_uniform_location =
         glGetUniformLocation(glamor_priv->solid_prog, "color");
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -178,9 +177,8 @@ glamor_fini_solid_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glDeleteProgram(glamor_priv->solid_prog);
-    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -196,7 +194,7 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glUseProgram(glamor_priv->solid_prog);
 
     glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
@@ -255,7 +253,6 @@ _glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
         free(vertices);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glamor_put_context(glamor_priv);
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
 }
@@ -338,13 +335,12 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
         return FALSE;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     if (!glamor_set_alu(screen, alu)) {
         if (alu == GXclear)
             fg_pixel = 0;
         else {
             glamor_fallback("unsupported alu %x\n", alu);
-            glamor_put_context(glamor_priv);
             return FALSE;
         }
     }
@@ -355,7 +351,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
     glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
 
     glamor_set_alu(screen, GXcopy);
-    glamor_put_context(glamor_priv);
 
     return TRUE;
 }
diff --git a/glamor/glamor_font.c b/glamor/glamor_font.c
index 47dfe2a..f747d59 100644
--- a/glamor/glamor_font.c
+++ b/glamor/glamor_font.c
@@ -89,7 +89,7 @@ glamor_font_get(ScreenPtr screen, FontPtr font)
     glamor_font->default_col = font->info.defaultCh;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glGenTextures(1, &glamor_font->texture_id);
     glActiveTexture(GL_TEXTURE0);
@@ -119,8 +119,6 @@ glamor_font_get(ScreenPtr screen, FontPtr font)
         }
     }
 
-    glamor_put_context(glamor_priv);
-
     return glamor_font;
 }
 
@@ -150,9 +148,8 @@ glamor_unrealize_font(ScreenPtr screen, FontPtr font)
     glamor_font->realized = FALSE;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(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
diff --git a/glamor/glamor_glx.c b/glamor/glamor_glx.c
index d56581c..db8e661 100644
--- a/glamor/glamor_glx.c
+++ b/glamor/glamor_glx.c
@@ -34,22 +34,13 @@
  */
 
 static void
-glamor_glx_get_context(struct glamor_context *glamor_ctx)
+glamor_glx_make_current(struct glamor_context *glamor_ctx)
 {
-    if (glamor_ctx->get_count++)
-        return;
-
     glXMakeCurrent(glamor_ctx->display, glamor_ctx->drawable_xid,
                    glamor_ctx->ctx);
 }
 
 
-static void
-glamor_glx_put_context(struct glamor_context *glamor_ctx)
-{
-    --glamor_ctx->get_count;
-}
-
 Bool
 glamor_glx_screen_init(struct glamor_context *glamor_ctx)
 {
@@ -63,8 +54,7 @@ glamor_glx_screen_init(struct glamor_context *glamor_ctx)
 
     glamor_ctx->drawable_xid = glXGetCurrentDrawable();
 
-    glamor_ctx->get_context = glamor_glx_get_context;
-    glamor_ctx->put_context = glamor_glx_put_context;
+    glamor_ctx->make_current = glamor_glx_make_current;
 
     return True;
 }
diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index c031747..1c511ff 100644
--- a/glamor/glamor_glyphblt.c
+++ b/glamor/glamor_glyphblt.c
@@ -54,7 +54,7 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs,
                                    &glamor_facet_poly_glyph_blt);
@@ -137,11 +137,9 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
     glDisable(GL_COLOR_LOGIC_OP);
     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;
 }
@@ -212,20 +210,18 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         return FALSE;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(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;
     }
 
@@ -281,8 +277,6 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 
-    glamor_put_context(glamor_priv);
-
     return TRUE;
 }
 
diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index a04ae82..42f5f65 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -1285,9 +1285,8 @@ 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_context(glamor_priv);
+                glamor_make_current(glamor_priv);
                 glFlush();
-                glamor_put_context(glamor_priv);
             }
         }
         else {
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index c24f342..28d6691 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -324,7 +324,7 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
         return;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (dyn_gen && glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]) {
         glDeleteProgram(glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][2]);
@@ -371,8 +371,6 @@ _glamor_create_radial_gradient_program(ScreenPtr screen, int stops_count,
     }
 
     glamor_priv->gradient_prog[SHADER_GRADIENT_RADIAL][index] = gradient_prog;
-
-    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -519,7 +517,7 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
         return;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     if (dyn_gen && 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;
@@ -562,8 +560,6 @@ _glamor_create_linear_gradient_program(ScreenPtr screen, int stops_count,
     }
 
     glamor_priv->gradient_prog[SHADER_GRADIENT_LINEAR][index] = gradient_prog;
-
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -595,7 +591,7 @@ glamor_fini_gradient_shader(ScreenPtr screen)
     int i = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     for (i = 0; i < 3; i++) {
         /* Linear Gradient */
@@ -607,8 +603,6 @@ glamor_fini_gradient_shader(ScreenPtr screen)
             glDeleteProgram(glamor_priv->gradient_prog
                             [SHADER_GRADIENT_RADIAL][i]);
     }
-
-    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -739,7 +733,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_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, 0, vertices);
@@ -749,8 +743,6 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    glamor_put_context(glamor_priv);
-
     return 1;
 }
 
@@ -892,7 +884,7 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     GLint r2_uniform_location = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     /* Create a pixmap with VBO. */
     pixmap = glamor_create_pixmap(screen,
@@ -1123,7 +1115,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    glamor_put_context(glamor_priv);
     return dst_picture;
 
  GRADIENT_FAIL:
@@ -1140,7 +1131,6 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glamor_put_context(glamor_priv);
     return NULL;
 }
 
@@ -1204,7 +1194,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     GLint pt_distance_uniform_location = 0;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     /* Create a pixmap with VBO. */
     pixmap = glamor_create_pixmap(screen,
@@ -1468,7 +1458,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    glamor_put_context(glamor_priv);
     return dst_picture;
 
  GRADIENT_FAIL:
@@ -1485,7 +1474,6 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glamor_put_context(glamor_priv);
     return NULL;
 }
 
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index a811f60..371e486 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -66,12 +66,10 @@ void
 glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *fbo, int x0, int y0,
                                   int width, int height)
 {
-    glamor_get_context(fbo->glamor_priv);
+    glamor_make_current(fbo->glamor_priv);
 
     glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
     glViewport(x0, y0, width, height);
-
-    glamor_put_context(fbo->glamor_priv);
 }
 
 void
@@ -707,7 +705,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
     int non_sub = 0;
     unsigned int iformat = 0;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     if (*tex == 0) {
         glGenTextures(1, tex);
         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
@@ -735,7 +733,6 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
 
     if (bits == NULL)
         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -832,7 +829,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_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
                           GL_FALSE, 2 * sizeof(float), vertices);
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
@@ -859,8 +856,6 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
     glDeleteTextures(1, &tex);
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
-    glamor_put_context(glamor_priv);
-
     if (need_free_bits)
         free(bits);
     return TRUE;
@@ -1140,7 +1135,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
     if (temp_fbo == NULL)
         return NULL;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     temp_xscale = 1.0 / w;
     temp_yscale = 1.0 / h;
 
@@ -1177,7 +1172,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glamor_put_context(glamor_priv);
     return temp_fbo;
 }
 
@@ -1255,7 +1249,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         fbo_y_off = 0;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
     if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
@@ -1286,7 +1280,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
         unsigned int temp_pbo;
         int yy;
 
-        glamor_get_context(glamor_priv);
+        glamor_make_current(glamor_priv);
         glGenBuffers(1, &temp_pbo);
         glBindBuffer(GL_PIXEL_PACK_BUFFER, temp_pbo);
         glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, GL_STREAM_READ);
@@ -1301,7 +1295,6 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
     }
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glamor_put_context(glamor_priv);
 
     if (need_post_conversion) {
         /* As OpenGL desktop version never enters here.
@@ -1473,10 +1466,9 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
         data = malloc(stride * pixmap->drawable.height);
     }
     else {
-        glamor_get_context(glamor_priv);
+        glamor_make_current(glamor_priv);
         if (pixmap_priv->base.fbo->pbo == 0)
             glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
-        glamor_put_context(glamor_priv);
         pbo = pixmap_priv->base.fbo->pbo;
     }
 
diff --git a/glamor/glamor_points.c b/glamor/glamor_points.c
index 0d58e55..d4525e2 100644
--- a/glamor/glamor_points.c
+++ b/glamor/glamor_points.c
@@ -52,7 +52,7 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (prog->failed)
         goto bail_ctx;
@@ -105,8 +105,6 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint
     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;
 
@@ -114,7 +112,6 @@ glamor_poly_point_gl(DrawablePtr drawable, GCPtr gc, int mode, int npt, DDXPoint
 
 bail_ctx:
     glDisable(GL_COLOR_LOGIC_OP);
-    glamor_put_context(glamor_priv);
 bail:
     return FALSE;
 }
diff --git a/glamor/glamor_rects.c b/glamor/glamor_rects.c
index 7731ede..3a5c3f3 100644
--- a/glamor/glamor_rects.c
+++ b/glamor/glamor_rects.c
@@ -57,7 +57,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (glamor_priv->glsl_version >= 130) {
         prog = glamor_use_program_fill(pixmap, gc,
@@ -144,11 +144,9 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
         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;
 }
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 2f3d950..294a4ae 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -316,13 +316,13 @@ 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_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     vs = glamor_create_composite_vs(key);
     if (vs == 0)
-        goto out;
+        return;
     fs = glamor_create_composite_fs(key);
     if (fs == 0)
-        goto out;
+        return;
 
     prog = glCreateProgram();
     glAttachShader(prog, vs);
@@ -363,9 +363,6 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key,
                 glGetUniformLocation(prog, "mask_repeat_mode");
         }
     }
-
- out:
-    glamor_put_context(glamor_priv);
 }
 
 static glamor_composite_shader *
@@ -406,7 +403,7 @@ glamor_init_composite_shaders(ScreenPtr screen)
     int eb_size;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glGenBuffers(1, &glamor_priv->ebo);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ebo);
 
@@ -416,8 +413,6 @@ glamor_init_composite_shaders(ScreenPtr screen)
     glamor_init_eb(eb, GLAMOR_COMPOSITE_VBO_VERT_CNT);
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb_size, eb, GL_STATIC_DRAW);
     free(eb);
-
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -428,7 +423,7 @@ glamor_fini_composite_shaders(ScreenPtr screen)
     int i, j, k;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDeleteBuffers(1, &glamor_priv->ebo);
 
@@ -439,8 +434,6 @@ glamor_fini_composite_shaders(ScreenPtr screen)
                 if (shader->prog)
                     glDeleteProgram(shader->prog);
             }
-
-    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -496,7 +489,7 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
     float wh[4];
     int repeat_type;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glActiveTexture(GL_TEXTURE0 + unit);
     glBindTexture(GL_TEXTURE_2D, pixmap_priv->base.fbo->tex);
     repeat_type = picture->repeatType;
@@ -564,7 +557,6 @@ glamor_set_composite_texture(glamor_screen_private *glamor_priv, int unit,
             repeat_type -= RepeatFix;
     }
     glUniform1i(repeat_location, repeat_type);
-    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -685,7 +677,7 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
 
     vert_size = n_verts * glamor_priv->vb_stride;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     vb = glamor_get_vbo_space(screen, vert_size, &vbo_offset);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
@@ -707,7 +699,6 @@ glamor_setup_composite_vbo(ScreenPtr screen, int n_verts)
                                             4 : 2) * sizeof(float));
         glEnableVertexAttribArray(GLAMOR_VERTEX_MASK);
     }
-    glamor_put_context(glamor_priv);
 
     return vb;
 }
@@ -717,7 +708,7 @@ glamor_flush_composite_rects(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (!glamor_priv->render_nr_verts)
         return;
@@ -730,7 +721,6 @@ glamor_flush_composite_rects(ScreenPtr screen)
         glDrawElements(GL_TRIANGLES, (glamor_priv->render_nr_verts * 3) / 2,
                        GL_UNSIGNED_SHORT, NULL);
     }
-    glamor_put_context(glamor_priv);
 }
 
 int pict_format_combine_tab[][3] = {
@@ -1112,7 +1102,7 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
 
     glamor_priv = dest_priv->base.glamor_priv;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glUseProgram(shader->prog);
 
     if (key->source == SHADER_SOURCE_SOLID) {
@@ -1146,8 +1136,6 @@ glamor_composite_set_shader_blend(glamor_pixmap_private *dest_priv,
         glEnable(GL_BLEND);
         glBlendFunc(op_info->source_blend, op_info->dest_blend);
     }
-
-    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -1202,7 +1190,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_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glamor_priv->has_source_coords = key.source != SHADER_SOURCE_SOLID;
     glamor_priv->has_mask_coords = (key.mask != SHADER_MASK_NONE &&
@@ -1328,7 +1316,6 @@ glamor_composite_with_shader(CARD8 op,
     glamor_priv->render_idle_cnt = 0;
     if (saved_source_format)
         source->format = saved_source_format;
-    glamor_put_context(glamor_priv);
 
     ret = TRUE;
     return ret;
diff --git a/glamor/glamor_spans.c b/glamor/glamor_spans.c
index 98842cd..46ba6c3 100644
--- a/glamor/glamor_spans.c
+++ b/glamor/glamor_spans.c
@@ -61,7 +61,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (glamor_priv->glsl_version >= 130) {
         prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
@@ -152,11 +152,9 @@ glamor_fill_spans_gl(DrawablePtr drawable,
         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;
 }
@@ -222,7 +220,7 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax,
 
     glamor_format_for_pixmap(pixmap, &format, &type);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
         BoxPtr                  box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y);
@@ -261,7 +259,6 @@ glamor_get_spans_gl(DrawablePtr drawable, int wmax,
         }
     }
 
-    glamor_put_context(glamor_priv);
     return TRUE;
 bail:
     return FALSE;
@@ -327,7 +324,7 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
     glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
     glamor_format_for_pixmap(pixmap, &format, &type);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -397,7 +394,6 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
         }
     }
 
-    glamor_put_context(glamor_priv);
     return TRUE;
 
 bail:
diff --git a/glamor/glamor_text.c b/glamor/glamor_text.c
index 0e4b74c..395116d 100644
--- a/glamor/glamor_text.c
+++ b/glamor/glamor_text.c
@@ -267,7 +267,7 @@ glamor_poly_text(DrawablePtr drawable, GCPtr gc,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_text_progs, &glamor_facet_poly_text);
 
@@ -279,8 +279,6 @@ glamor_poly_text(DrawablePtr drawable, GCPtr gc,
 
     glDisable(GL_COLOR_LOGIC_OP);
 
-    glamor_put_context(glamor_priv);
-
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
 
@@ -289,7 +287,6 @@ glamor_poly_text(DrawablePtr drawable, GCPtr gc,
 
 bail_ctx:
     glDisable(GL_COLOR_LOGIC_OP);
-    glamor_put_context(glamor_priv);
 bail:
     return FALSE;
 }
@@ -420,7 +417,7 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
 
     glamor_get_glyphs(gc->font, glamor_font, count, chars, sixteen, charinfo);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (TERMINALFONT(gc->font))
         prog = &glamor_priv->te_text_prog;
@@ -482,8 +479,6 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
     (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;
 
@@ -491,7 +486,6 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
 
 bail:
     glDisable(GL_COLOR_LOGIC_OP);
-    glamor_put_context(glamor_priv);
     return FALSE;
 }
 
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
index 9e115ca..4e47976 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_context(glamor_priv);
+    glamor_make_current(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);
@@ -82,7 +82,6 @@ glamor_init_tile_shader(ScreenPtr screen)
 
     glamor_priv->tile_wh =
         glGetUniformLocation(glamor_priv->tile_prog, "wh");
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -91,9 +90,8 @@ glamor_fini_tile_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glDeleteProgram(glamor_priv->tile_prog);
-    glamor_put_context(glamor_priv);
 }
 
 static void
@@ -123,7 +121,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_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glUseProgram(glamor_priv->tile_prog);
 
     glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
@@ -155,7 +153,6 @@ _glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glamor_put_context(glamor_priv);
 
     glamor_priv->state = RENDER_STATE;
     glamor_priv->render_idle_cnt = 0;
@@ -193,10 +190,9 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
         goto fail;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     if (!glamor_set_alu(screen, alu)) {
         glamor_fallback("unsupported alu %x\n", alu);
-        glamor_put_context(glamor_priv);
         goto fail;
     }
 
@@ -290,7 +286,6 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
         _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
 
     glamor_set_alu(screen, GXcopy);
-    glamor_put_context(glamor_priv);
     return TRUE;
  fail:
     return FALSE;
diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
index 0378bb0..ad875c9 100644
--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -70,7 +70,7 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
 
     glamor_format_for_pixmap(pixmap, &format, &type);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -127,7 +127,6 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
-    glamor_put_context(glamor_priv);
 }
 
 /*
@@ -180,7 +179,7 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
 
     glamor_format_for_pixmap(pixmap, &format, &type);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
     glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
@@ -226,7 +225,6 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
     glPixelStorei(GL_PACK_SKIP_ROWS, 0);
     glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
-    glamor_put_context(glamor_priv);
 }
 
 /*
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index c76b8bb..4aba469 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -235,14 +235,13 @@ glamor_flush_composite_triangles(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glamor_put_vbo_space(screen);
 
     if (!glamor_priv->render_nr_verts)
         return;
 
     glDrawArrays(GL_TRIANGLES, 0, glamor_priv->render_nr_verts);
-    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -627,7 +626,7 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
 
     vert_size = n_verts * glamor_priv->vb_stride;
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
@@ -667,8 +666,6 @@ glamor_setup_composite_vbo_for_trapezoid(ScreenPtr screen, int n_verts)
                           vbo_offset + stride * sizeof(float));
     glEnableVertexAttribArray(GLAMOR_VERTEX_RIGHT_PARAM);
 
-    glamor_put_context(glamor_priv);
-
     return vb;
 }
 
@@ -811,7 +808,7 @@ _glamor_trapezoids_with_shader(CARD8 op,
         goto TRAPEZOID_OUT;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     box = REGION_RECTS(&region);
     nbox = REGION_NUM_RECTS(&region);
@@ -979,7 +976,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
     glDisable(GL_BLEND);
-    glamor_put_context(glamor_priv);
 
  TRAPEZOID_OUT:
     if (box) {
@@ -1332,7 +1328,7 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
         "}\n";
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glamor_priv->trapezoid_prog = glCreateProgram();
 
@@ -1354,8 +1350,6 @@ glamor_init_trapezoid_shader(ScreenPtr screen)
                          GLAMOR_VERTEX_RIGHT_PARAM, "v_right_param");
 
     glamor_link_glsl_prog(screen, glamor_priv->trapezoid_prog, "trapezoid");
-
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -1364,9 +1358,8 @@ glamor_fini_trapezoid_shader(ScreenPtr screen)
     glamor_screen_private *glamor_priv;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glDeleteProgram(glamor_priv->trapezoid_prog);
-    glamor_put_context(glamor_priv);
 }
 
 static Bool
@@ -1406,7 +1399,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
         return FALSE;
     }
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 
@@ -1564,7 +1557,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);
-    glamor_put_context(glamor_priv);
     return TRUE;
 }
 
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index 56ef6a9..4c1581e 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1499,18 +1499,12 @@ __fls(unsigned long x)
 #endif
 
 static inline void
-glamor_get_context(glamor_screen_private * glamor_priv)
+glamor_make_current(glamor_screen_private *glamor_priv)
 {
     if (lastGLContext != &glamor_priv->ctx) {
         lastGLContext = &glamor_priv->ctx;
-        glamor_priv->ctx.get_context(&glamor_priv->ctx);
+        glamor_priv->ctx.make_current(&glamor_priv->ctx);
     }
 }
 
-static inline void
-glamor_put_context(glamor_screen_private * glamor_priv)
-{
-    glamor_priv->ctx.put_context(&glamor_priv->ctx);
-}
-
 #endif
diff --git a/glamor/glamor_vbo.c b/glamor/glamor_vbo.c
index 2731692..c678559 100644
--- a/glamor/glamor_vbo.c
+++ b/glamor/glamor_vbo.c
@@ -48,7 +48,7 @@ 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);
+    glamor_make_current(glamor_priv);
 
     glBindBuffer(GL_ARRAY_BUFFER, glamor_priv->vbo);
 
@@ -79,7 +79,6 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
                      */
                     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);
                 }
@@ -130,8 +129,6 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
         data = glamor_priv->vb;
     }
 
-    glamor_put_context(glamor_priv);
-
     return data;
 }
 
@@ -140,7 +137,7 @@ glamor_put_vbo_space(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     if (glamor_priv->has_buffer_storage) {
         /* If we're in the ARB_buffer_storage path, we have a
@@ -155,8 +152,6 @@ glamor_put_vbo_space(ScreenPtr screen)
     }
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
-
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -164,11 +159,9 @@ glamor_init_vbo(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glGenBuffers(1, &glamor_priv->vbo);
-
-    glamor_put_context(glamor_priv);
 }
 
 void
@@ -176,11 +169,9 @@ glamor_fini_vbo(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
 
     glDeleteBuffers(1, &glamor_priv->vbo);
     if (!glamor_priv->has_map_buffer_range)
         free(glamor_priv->vb);
-
-    glamor_put_context(glamor_priv);
 }
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 4e60fa3..369b02b 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -97,7 +97,7 @@ glamor_init_xv_shader(ScreenPtr screen)
     GLint fs_prog, vs_prog;
 
     glamor_priv = glamor_get_screen_private(screen);
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glamor_priv->xv_prog = glCreateProgram();
 
     vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, xv_vs);
@@ -110,8 +110,6 @@ glamor_init_xv_shader(ScreenPtr screen)
     glBindAttribLocation(glamor_priv->xv_prog,
                          GLAMOR_VERTEX_SOURCE, "v_texcoord0");
     glamor_link_glsl_prog(screen, glamor_priv->xv_prog, "xv");
-
-    glamor_put_context(glamor_priv);
 }
 
 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
@@ -316,7 +314,7 @@ glamor_display_textured_video(glamor_port_private *port_priv)
                                   &src_yscale[i]);
         }
     }
-    glamor_get_context(glamor_priv);
+    glamor_make_current(glamor_priv);
     glUseProgram(glamor_priv->xv_prog);
 
     uloc = glGetUniformLocation(glamor_priv->xv_prog, "offsetyco");
@@ -404,7 +402,6 @@ glamor_display_textured_video(glamor_port_private *port_priv)
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 
-    glamor_put_context(glamor_priv);
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
 
commit 11ff12d4e74c0b514cb62cc47df9770c91e5002a
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 14 17:29:31 2014 -0700

    glamor: Stop unsetting the EGL context in put_context().
    
    This matches the Xephyr behavior.  Now that we know when to reset the
    context in the presence of GLX, we don't need to try to keep our stuff
    from being smashed by GLX.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 33a95a0..a16022b 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -112,11 +112,7 @@ glamor_egl_get_context(struct glamor_context *glamor_ctx)
 static void
 glamor_egl_put_context(struct glamor_context *glamor_ctx)
 {
-    if (--glamor_ctx->get_count)
-        return;
-
-    eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
-                   EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    --glamor_ctx->get_count;
 }
 
 static EGLImageKHR
commit b5e394b3f5d80749af0148611df2eb009e7bf823
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 14 17:20:12 2014 -0700

    glamor: Use lastGLContext to coordinate the context with GLX.
    
    This gets us some more context changes that are needed to make sure
    the two sides render to the right drawables and manipulate the right
    objects.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 9b6b323..33a95a0 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -100,14 +100,12 @@ glamor_egl_get_context(struct glamor_context *glamor_ctx)
     if (glamor_ctx->get_count++)
         return;
 
-    if (glamor_ctx->ctx != eglGetCurrentContext()) {
-        eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
-                       EGL_NO_SURFACE, EGL_NO_CONTEXT);
-        if (!eglMakeCurrent(glamor_ctx->display,
-                            EGL_NO_SURFACE, EGL_NO_SURFACE,
-                            glamor_ctx->ctx)) {
-            FatalError("Failed to make EGL context current\n");
-        }
+    eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
+                   EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    if (!eglMakeCurrent(glamor_ctx->display,
+                        EGL_NO_SURFACE, EGL_NO_SURFACE,
+                        glamor_ctx->ctx)) {
+        FatalError("Failed to make EGL context current\n");
     }
 }
 
diff --git a/glamor/glamor_glx.c b/glamor/glamor_glx.c
index 8f47c3d..d56581c 100644
--- a/glamor/glamor_glx.c
+++ b/glamor/glamor_glx.c
@@ -36,15 +36,9 @@
 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);
 }
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index 53b7d9b..56ef6a9 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -1501,7 +1501,10 @@ __fls(unsigned long x)
 static inline void
 glamor_get_context(glamor_screen_private * glamor_priv)
 {
-    glamor_priv->ctx.get_context(&glamor_priv->ctx);
+    if (lastGLContext != &glamor_priv->ctx) {
+        lastGLContext = &glamor_priv->ctx;
+        glamor_priv->ctx.get_context(&glamor_priv->ctx);
+    }
 }
 
 static inline void
commit ab6e958a2e611b03e475c16d10beb9961d8dffc8
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 9 10:23:01 2014 -0700

    glx: Make sure that DRI2/swrast calls haven't changed the GL context.
    
    These functions are called from the GL driver, in some series of GL
    calls by GLX.  If some server component (like glamor CreatePixmap for
    GetBuffers()) changes the GL context on us, we need to set it back or
    the later GL calls will land in the glamor context instead of the GLX
    context.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 94476dd..7b368d2 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -121,6 +121,7 @@ copy_box(__GLXdrawable * drawable,
 {
     BoxRec box;
     RegionRec region;
+    __GLXcontext *cx = lastGLContext;
 
     box.x1 = x;
     box.y1 = y;
@@ -129,6 +130,10 @@ copy_box(__GLXdrawable * drawable,
     RegionInit(&region, &box, 0);
 
     DRI2CopyRegion(drawable->pDraw, &region, dst, src);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
 }
 
 static void
@@ -198,26 +203,37 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
     __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
     __GLXDRIscreen *screen = priv->screen;
     CARD64 unused;
+    __GLXcontext *cx = lastGLContext;
+    int status;
 
     if (screen->flush) {
         (*screen->flush->flush) (priv->driDrawable);
         (*screen->flush->invalidate) (priv->driDrawable);
     }
 
-    if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
-                        __glXdriSwapEvent, drawable) != Success)
-        return FALSE;
+    status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+                             __glXdriSwapEvent, drawable);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
 
-    return TRUE;
+    return status == Success;
 }
 
 static int
 __glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
 {
+    __GLXcontext *cx = lastGLContext;
+
     if (interval <= 0)          /* || interval > BIGNUM? */
         return GLX_BAD_VALUE;
 
     DRI2SwapInterval(drawable->pDraw, interval);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
 
     return 0;
 }
@@ -270,7 +286,16 @@ static Bool
 __glXDRIcontextWait(__GLXcontext * baseContext,
                     __GLXclientState * cl, int *error)
 {
-    if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
+    __GLXcontext *cx = lastGLContext;
+    Bool ret;
+
+    ret = DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
+
+    if (ret) {
         *error = cl->client->noClientException;
         return TRUE;
     }
@@ -594,6 +619,8 @@ __glXDRIscreenCreateDrawable(ClientPtr client,
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
     __GLXDRIdrawable *private;
+    __GLXcontext *cx = lastGLContext;
+    Bool ret;
 
     private = calloc(1, sizeof *private);
     if (private == NULL)
@@ -612,9 +639,15 @@ __glXDRIscreenCreateDrawable(ClientPtr client,
     private->base.waitGL = __glXDRIdrawableWaitGL;
     private->base.waitX = __glXDRIdrawableWaitX;
 
-    if (DRI2CreateDrawable2(client, pDraw, drawId,
-                            __glXDRIinvalidateBuffers, private,
-                            &private->dri2_id)) {
+    ret = DRI2CreateDrawable2(client, pDraw, drawId,
+                              __glXDRIinvalidateBuffers, private,
+                              &private->dri2_id);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
+
+    if (ret) {
         free(private);
         return NULL;
     }
@@ -636,9 +669,15 @@ dri2GetBuffers(__DRIdrawable * driDrawable,
     DRI2BufferPtr *buffers;
     int i;
     int j;
+    __GLXcontext *cx = lastGLContext;
 
     buffers = DRI2GetBuffers(private->base.pDraw,
                              width, height, attachments, count, out_count);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
+
     if (*out_count > MAX_DRAWABLE_BUFFERS) {
         *out_count = 0;
         return NULL;
@@ -680,10 +719,16 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
     DRI2BufferPtr *buffers;
     int i;
     int j = 0;
+    __GLXcontext *cx = lastGLContext;
 
     buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
                                        width, height, attachments, count,
                                        out_count);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
+
     if (*out_count > MAX_DRAWABLE_BUFFERS) {
         *out_count = 0;
         return NULL;
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
index 6fa3288..c30ce9a 100644
--- a/glx/glxdriswrast.c
+++ b/glx/glxdriswrast.c
@@ -337,6 +337,7 @@ swrastPutImage(__DRIdrawable * draw, int op,
     __GLXDRIdrawable *drawable = loaderPrivate;
     DrawablePtr pDraw = drawable->base.pDraw;
     GCPtr gc;
+    __GLXcontext *cx = lastGLContext;
 
     switch (op) {
     case __DRI_SWRAST_IMAGE_OP_DRAW:
@@ -352,6 +353,10 @@ swrastPutImage(__DRIdrawable * draw, int op,
     ValidateGC(pDraw, gc);
 
     gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, data);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
 }
 
 static void
@@ -361,8 +366,13 @@ swrastGetImage(__DRIdrawable * draw,
     __GLXDRIdrawable *drawable = loaderPrivate;
     DrawablePtr pDraw = drawable->base.pDraw;
     ScreenPtr pScreen = pDraw->pScreen;
+    __GLXcontext *cx = lastGLContext;
 
     pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
+    if (cx != lastGLContext) {
+        lastGLContext = cx;
+        cx->makeCurrent(cx);
+    }
 }
 
 static const __DRIswrastLoaderExtension swrastLoaderExtension = {
commit f3f2fb6baac3d2b248eb4b0da13fe95e9dc3de7d
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 9 11:25:32 2014 -0700

    glx: Refactor DRI2CopyRegion calls.
    
    I needed to add some code to each one, so it's a good time to make a
    helper func.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 5d1a45b..94476dd 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -115,55 +115,49 @@ __glXDRIdrawableDestroy(__GLXdrawable * drawable)
 }
 
 static void
-__glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
-                              int x, int y, int w, int h)
+copy_box(__GLXdrawable * drawable,
+         int dst, int src,
+         int x, int y, int w, int h)
 {
-    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
     BoxRec box;
     RegionRec region;
 
     box.x1 = x;
-    box.y1 = private->height - y - h;
+    box.y1 = y;
     box.x2 = x + w;
-    box.y2 = private->height - y;
+    box.y2 = y + h;
     RegionInit(&region, &box, 0);
 
-    DRI2CopyRegion(drawable->pDraw, &region,
-                   DRI2BufferFrontLeft, DRI2BufferBackLeft);
+    DRI2CopyRegion(drawable->pDraw, &region, dst, src);
 }
 
 static void
-__glXDRIdrawableWaitX(__GLXdrawable * drawable)
+__glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
+                              int x, int y, int w, int h)
 {
     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
-    BoxRec box;
-    RegionRec region;
 
-    box.x1 = 0;
-    box.y1 = 0;
-    box.x2 = private->width;
-    box.y2 = private->height;
-    RegionInit(&region, &box, 0);
+    copy_box(drawable, x, private->height - y - h,
+             w, h,
+             DRI2BufferFrontLeft, DRI2BufferBackLeft);
+}
 
-    DRI2CopyRegion(drawable->pDraw, &region,
-                   DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+static void
+__glXDRIdrawableWaitX(__GLXdrawable * drawable)
+{
+    __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+
+    copy_box(drawable, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft,
+             0, 0, private->width, private->height);
 }
 
 static void
 __glXDRIdrawableWaitGL(__GLXdrawable * drawable)
 {
     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
-    BoxRec box;
-    RegionRec region;
-
-    box.x1 = 0;
-    box.y1 = 0;
-    box.x2 = private->width;
-    box.y2 = private->height;
-    RegionInit(&region, &box, 0);
 
-    DRI2CopyRegion(drawable->pDraw, &region,
-                   DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+    copy_box(drawable, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
+             0, 0, private->width, private->height);
 }
 
 static void
commit 008f1ab31e8ac6be8f3fb11f19cdf8674be318dd
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Apr 17 18:28:54 2014 -0700

    glx: Unconditionally clear lastGLContext on loseCurrent().
    
    This hook calls unbindContext in the DRI driver interface, which
    unsets the dispatch table, regardless of whether the context argument
    was the current one or not.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glx/glxext.c b/glx/glxext.c
index 9855767..c0142fe 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -135,8 +135,7 @@ DrawableGone(__GLXdrawable * glxPriv, XID xid)
 		(c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
             /* just force a re-bind the next time through */
             (*c->loseCurrent) (c);
-            if (c == lastGLContext)
-                lastGLContext = NULL;
+            lastGLContext = NULL;
         }
         if (c->drawPriv == glxPriv)
             c->drawPriv = NULL;
@@ -290,6 +289,7 @@ glxClientCallback(CallbackListPtr *list, void *closure, void *data)
             next = c->next;
             if (c->currentClient == pClient) {
                 c->loseCurrent(c);
+                lastGLContext = NULL;
                 c->currentClient = NULL;
                 __glXFreeContext(c);
             }
commit 789509ef5324ce9141222fa92dea51b5cc777209
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Apr 17 18:23:51 2014 -0700

    glx: Move GLX MakeCurrent lastGLContext updates next to makeCurrent().
    
    We want to make sure that lastGLContext is set correctly during
    makeCurrent, because we may have recursive GL context changes in the
    DRI2 interfaces due to glamor.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index a451d2b..fb236b6 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -434,9 +434,6 @@ static void
 StopUsingContext(__GLXcontext * glxc)
 {
     if (glxc) {
-        if (glxc == lastGLContext) {
-            lastGLContext = NULL;
-        }
         glxc->currentClient = NULL;
         if (!glxc->idExists) {
             FreeResourceByType(glxc->id, __glXContextRes, FALSE);
@@ -447,7 +444,6 @@ StopUsingContext(__GLXcontext * glxc)
 static void
 StartUsingContext(__GLXclientState * cl, __GLXcontext * glxc)
 {
-    lastGLContext = glxc;
     glxc->currentClient = cl->client;
 }
 
@@ -639,7 +635,9 @@ DoMakeCurrent(__GLXclientState * cl,
         glxc->readPriv = readPriv;
 
         /* make the context current */
+        lastGLContext = glxc;
         if (!(*glxc->makeCurrent) (glxc)) {
+            lastGLContext = NULL;
             glxc->drawPriv = NULL;
             glxc->readPriv = NULL;
             return __glXError(GLXBadContext);
diff --git a/glx/glxext.c b/glx/glxext.c
index 85fd219..9855767 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -444,14 +444,15 @@ __glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
 
     /* Make this context the current one for the GL. */
     if (!cx->isDirect) {
+        lastGLContext = cx;
         if (!(*cx->makeCurrent) (cx)) {
             /* Bind failed, and set the error code.  Bummer */
+            lastGLContext = NULL;
             cl->client->errorValue = cx->id;
             *error = __glXError(GLXBadContextState);
             return 0;
         }
     }
-    lastGLContext = cx;
     return cx;
 }
 
commit abf12027063dbe22bec1d055ad8db365cf07395a
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Apr 17 18:18:49 2014 -0700

    glx: Move the GLX variable caching what GL context is current to dix.
    
    GLX is trying to track whether the context it wants is current, to
    avoid the glFlush() (and the rest of the overhead) that occurs on all
    MakeCurrent calls.  However, its cache can be incorrect now that
    glamor exists.  This is a step toward getting glamor to coordinate
    with GLX.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/dix/dixutils.c b/dix/dixutils.c
index 5de74c8..cdd370b 100644
--- a/dix/dixutils.c
+++ b/dix/dixutils.c
@@ -866,3 +866,28 @@ InitCallbackManager(void)
 {
     DeleteCallbackManager();
 }
+
+/**
+ * Coordinates the global GL context used by modules in the X Server
+ * doing rendering with OpenGL.
+ *
+ * When setting a GL context (glXMakeCurrent() or eglMakeCurrent()),
+ * there is an expensive implied glFlush() required by the GLX and EGL
+ * APIs, so modules don't want to have to do it on every request.  But
+ * the individual modules using GL also don't know about each other,
+ * so they have to coordinate who owns the current context.
+ *
+ * When you're about to do a MakeCurrent, you should set this variable
+ * to your context's address, and you can skip MakeCurrent if it's
+ * already set to yours.
+ *
+ * When you're about to do a DestroyContext, you should set this to
+ * NULL if it's set to your context.
+ *
+ * When you're about to do an unbindContext on a DRI driver, you
+ * should set this to NULL.  Despite the unbindContext interface
+ * sounding like it only unbinds the passed in context, it actually
+ * unconditionally clears the dispatch table even if the given
+ * context wasn't current.
+ */
+void *lastGLContext = NULL;
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 187e426..a451d2b 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -188,7 +188,7 @@ validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
 void
 __glXContextDestroy(__GLXcontext * context)
 {
-    __glXFlushContextCache();
+    lastGLContext = NULL;
 }
 
 static void
@@ -434,9 +434,8 @@ static void
 StopUsingContext(__GLXcontext * glxc)
 {
     if (glxc) {
-        if (glxc == __glXLastContext) {
-            /* Tell server GL library */
-            __glXLastContext = 0;
+        if (glxc == lastGLContext) {
+            lastGLContext = NULL;
         }
         glxc->currentClient = NULL;
         if (!glxc->idExists) {
@@ -448,7 +447,7 @@ StopUsingContext(__GLXcontext * glxc)
 static void
 StartUsingContext(__GLXclientState * cl, __GLXcontext * glxc)
 {
-    __glXLastContext = glxc;
+    lastGLContext = glxc;
     glxc->currentClient = cl->client;
 }
 
@@ -627,7 +626,7 @@ DoMakeCurrent(__GLXclientState * cl,
         if (!(*prevglxc->loseCurrent) (prevglxc)) {
             return __glXError(GLXBadContext);
         }
-        __glXFlushContextCache();
+        lastGLContext = NULL;
         if (!prevglxc->isDirect) {
             prevglxc->drawPriv = NULL;
             prevglxc->readPriv = NULL;
diff --git a/glx/glxext.c b/glx/glxext.c
index c9b8cc5..85fd219 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -48,12 +48,6 @@
 #include "indirect_util.h"
 
 /*
-** The last context used by the server.  It is the context that is current
-** from the server's perspective.
-*/
-__GLXcontext *__glXLastContext;
-
-/*
 ** X resources.
 */
 RESTYPE __glXContextRes;
@@ -79,7 +73,7 @@ static int __glXDispatch(ClientPtr);
 static void
 ResetExtension(ExtensionEntry * extEntry)
 {
-    __glXFlushContextCache();
+    lastGLContext = NULL;
 }
 
 /*
@@ -141,8 +135,8 @@ DrawableGone(__GLXdrawable * glxPriv, XID xid)
 		(c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
             /* just force a re-bind the next time through */
             (*c->loseCurrent) (c);
-            if (c == __glXLastContext)
-                __glXFlushContextCache();
+            if (c == lastGLContext)
+                lastGLContext = NULL;
         }
         if (c->drawPriv == glxPriv)
             c->drawPriv = NULL;
@@ -203,8 +197,8 @@ __glXFreeContext(__GLXcontext * cx)
 
     free(cx->feedbackBuf);
     free(cx->selectBuf);
-    if (cx == __glXLastContext) {
-        __glXFlushContextCache();
+    if (cx == lastGLContext) {
+        lastGLContext = NULL;
     }
 
     /* We can get here through both regular dispatching from
@@ -406,12 +400,6 @@ GlxExtensionInit(void)
 
 /************************************************************************/
 
-void
-__glXFlushContextCache(void)
-{
-    __glXLastContext = 0;
-}
-
 /*
 ** Make a context the current one for the GL (in this implementation, there
 ** is only one instance of the GL, and we use it to serve all GL clients by
@@ -449,7 +437,7 @@ __glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
     if (cx->wait && (*cx->wait) (cx, cl, error))
         return NULL;
 
-    if (cx == __glXLastContext) {
+    if (cx == lastGLContext) {
         /* No need to re-bind */
         return cx;
     }
@@ -463,7 +451,7 @@ __glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
             return 0;
         }
     }
-    __glXLastContext = cx;
+    lastGLContext = cx;
     return cx;
 }
 
diff --git a/glx/glxserver.h b/glx/glxserver.h
index 3f2ae35..a324b29 100644
--- a/glx/glxserver.h
+++ b/glx/glxserver.h
@@ -84,7 +84,6 @@ void __glXScreenInitVisuals(__GLXscreen * screen);
 /*
 ** The last context used (from the server's persective) is cached.
 */
-extern __GLXcontext *__glXLastContext;
 extern __GLXcontext *__glXForceCurrent(__GLXclientState *, GLXContextTag,
                                        int *);
 
diff --git a/include/dix.h b/include/dix.h
index 8371df0..f42e236 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -608,4 +608,6 @@ CorePointerProc(DeviceIntPtr dev, int what);
 extern _X_HIDDEN int
 CoreKeyboardProc(DeviceIntPtr dev, int what);
 
+extern _X_EXPORT void *lastGLContext;
+
 #endif                          /* DIX_H */
commit f12221cbd8ff33070fa2ca086bccf7ed32115f0e
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 16 16:16:21 2014 -0700

    glamor: Fix a missing set of the GL context.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index d37de9b..9b6b323 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -166,10 +166,14 @@ glamor_get_flink_name(int fd, int handle, int *name)
 }
 
 static Bool
-glamor_create_texture_from_image(struct glamor_egl_screen_private
-                                 *glamor_egl,
+glamor_create_texture_from_image(ScreenPtr screen,
                                  EGLImageKHR image, GLuint * texture)
 {
+    struct glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(screen);
+
+    glamor_get_context(glamor_priv);
+
     glGenTextures(1, texture);
     glBindTexture(GL_TEXTURE_2D, *texture);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -177,6 +181,9 @@ glamor_create_texture_from_image(struct glamor_egl_screen_private
 
     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
     glBindTexture(GL_TEXTURE_2D, 0);
+
+    glamor_put_context(glamor_priv);
+
     return TRUE;
 }
 
@@ -211,7 +218,7 @@ glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
     gbm_bo_destroy(bo);
     if (image == EGL_NO_IMAGE_KHR)
         return 0;
-    glamor_create_texture_from_image(glamor_egl, image, &texture);
+    glamor_create_texture_from_image(screen, image, &texture);
     eglDestroyImageKHR(glamor_egl->display, image);
 
     return texture;
@@ -312,7 +319,7 @@ glamor_egl_create_textured_pixmap(PixmapPtr pixmap, int handle, int stride)
         glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY);
         goto done;
     }
-    glamor_create_texture_from_image(glamor_egl, image, &texture);
+    glamor_create_texture_from_image(screen, image, &texture);
     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_texture(pixmap, texture);
     pixmap_priv->base.image = image;
@@ -348,7 +355,7 @@ glamor_egl_create_textured_pixmap_from_gbm_bo(PixmapPtr pixmap, void *bo)
         glamor_set_pixmap_type(pixmap, GLAMOR_DRM_ONLY);
         goto done;
     }
-    glamor_create_texture_from_image(glamor_egl, image, &texture);
+    glamor_create_texture_from_image(screen, image, &texture);
     glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
     glamor_set_pixmap_texture(pixmap, texture);
     pixmap_priv->base.image = image;
commit e924034269532979f1e88947ee9c33d30461edae
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Apr 21 10:56:38 2014 -0700

    glamor: Fix accelerated rendering of GTK's ARGB vs xBGR composites.
    
    There is some complicated code to support tweaking the format as we
    upload from a SHM pixmap (aka the GTK icon cache), but if we weren't
    sourcing from a SHM pixmap we just forgot to check that the formats
    matched at all.
    
    We could potentially be a little more discerning here (xRGB source and
    ARGB mask would be fine, for example), but this will all change with
    texture views anyway, so just get the rendering working for 1.16
    release.
    
    Fixes the new rendercheck gtk_argb_xbgr test.
    
    v2: Squash in keithp's fix for checking that we have a non-NULL
        pixmap, and reword the comment even more.
    
    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 cdf8eff..2f3d950 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1038,6 +1038,16 @@ glamor_composite_choose_shader(CARD8 op,
     }
 #endif
 
+    /* If the source and mask are two differently-formatted views of
+     * the same pixmap bits, and the pixmap was already uploaded (so
+     * the dynamic code above doesn't apply), then fall back to
+     * software.  We should use texture views to fix this properly.
+     */
+    if (source_pixmap && source_pixmap == mask_pixmap &&
+        source->format != mask->format) {
+        goto fail;
+    }
+
     /*Before enter the rendering stage, we need to fixup
      * transformed source and mask, if the transform is not int translate. */
     if (key.source != SHADER_SOURCE_SOLID
commit 4bbee6761d49478fa40ec5daa2797f13ae96ce5c
Author: Jamey Sharp <jamey at minilop.net>
Date:   Fri Apr 18 09:31:09 2014 -0700

    Make glamor build with --enable-debug.
    
    Bad anholt, no biscuit. Broken in commit
    4c9a20072552c52b3763bd73e7a7e9b9cb8b4993.
    
    Signed-off-by: Jamey Sharp <jamey at minilop.net>
    Cc: Eric Anholt <eric at anholt.net>
    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 7b1615d..5b341d3 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -127,7 +127,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
          */
         assert(!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) ||
                access == GLAMOR_ACCESS_RO ||
-               pixmap_priv->base.mapped_for_write);
+               pixmap_priv->base.map_access == GLAMOR_ACCESS_RW);
         return TRUE;
     }
     pixmap_priv->base.map_access = access;
commit ba2432a020a9f9bd0892f643117795336ba0fc16
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Apr 10 11:34:28 2014 -0400

    xfixes: Forbid manipulating clip for source-only pictures (#28968)
    
    Just throw BadPicture instead of crashing.  It's not currently a
    meaningful thing to do anyway, RenderSetPictureRectangles would error if
    you tried (which this patch changes to BadPicture as well for
    consistency).  The problem with trying to do it is if the clip is
    specified as a pixmap then we try to convert it to a region, and
    ->BitmapToRegion requires a ScreenPtr, and source-only pictures don't
    have one.
    
    I can imagine a use for client clip on source-only pictures, so if we
    really wanted to allow this, probably the way forward is to always store
    the clip as a region internally, and when setting the clip _from_ a
    pixmap, look up BitmapToRegion relative to the pixmap not the picture.
    But since clearly nobody can be relying on it working...
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/render/render.c b/render/render.c
index 3b7151a..9ac4a98 100644
--- a/render/render.c
+++ b/render/render.c
@@ -638,7 +638,7 @@ ProcRenderSetPictureClipRectangles(ClientPtr client)
     REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
     VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
     if (!pPicture->pDrawable)
-        return BadDrawable;
+        return RenderErrBase + BadPicture;
 
     nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq);
     if (nr & 4)
diff --git a/xfixes/region.c b/xfixes/region.c
index cc8f1a5..f9de525 100644
--- a/xfixes/region.c
+++ b/xfixes/region.c
@@ -269,6 +269,9 @@ ProcXFixesCreateRegionFromPicture(ClientPtr client)
 
     VERIFY_PICTURE(pPicture, stuff->picture, client, DixGetAttrAccess);
 
+    if (!pPicture->pDrawable)
+        return RenderErrBase + BadPicture;
+
     switch (pPicture->clientClipType) {
     case CT_PIXMAP:
         pRegion = BitmapToRegion(pPicture->pDrawable->pScreen,
@@ -750,6 +753,9 @@ ProcXFixesSetPictureClipRegion(ClientPtr client)
     VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
     VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
 
+    if (!pPicture->pDrawable)
+        return RenderErrBase + BadPicture;
+
     return SetPictureClipRegion(pPicture, stuff->xOrigin, stuff->yOrigin,
                                 pRegion);
 }
commit 70e564104b69bc53d29633f392f2c1ab94caddc9
Author: Dominik Behr <dbehr at chromium.org>
Date:   Tue Apr 1 20:36:13 2014 -0700

    xf86RandR12: use correct gamma size when allocating gamma table
    
    When setting crtc->gamma_size to randr_crtc->gammaSize we should
    use randr_crtc->gammaSize to allocate new gamma table in crtc.
    Currently, if randr_crtc->gammaSize > crtc->gammaSize the subsequent
    memcpy will overwrite memory beyond the end of gamma table.
    
    Signed-off-by: Dominik Behr <dbehr at chromium.org>
    Reviewed-by: Stéphane Marchesin <marcheu at chromium.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 66139dc..8a04dfc 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1256,12 +1256,13 @@ xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc)
         CARD16 *tmp_ptr;
 
         tmp_ptr =
-            realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof(CARD16));
+            realloc(crtc->gamma_red,
+                    3 * randr_crtc->gammaSize * sizeof(CARD16));
         if (!tmp_ptr)
             return FALSE;
         crtc->gamma_red = tmp_ptr;
-        crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
-        crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
+        crtc->gamma_green = crtc->gamma_red + randr_crtc->gammaSize;
+        crtc->gamma_blue = crtc->gamma_green + randr_crtc->gammaSize;
     }
 
     crtc->gamma_size = randr_crtc->gammaSize;
commit 35d275c7519570ceaf82cd5e7a663a8a5be4d441
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Apr 4 08:38:33 2014 +0100

    os: Initialize the set of signals to be suppressed during our handler.
    
    Fixes a valgrind complaint:
    
    ==8805== Syscall param rt_sigaction(act->sa_mask) points to uninitialised byte(s)
    ==8805==    at 0x5EB8315: __libc_sigaction (sigaction.c:66)
    ==8805==    by 0x5B13DA: busfault_init (busfault.c:145)
    ==8805==    by 0x5A60A2: OsInit (osinit.c:191)
    ==8805==    by 0x46EBA2: dix_main (main.c:163)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/os/busfault.c b/os/busfault.c
index 43bb6ea..ac0268f 100644
--- a/os/busfault.c
+++ b/os/busfault.c
@@ -142,6 +142,7 @@ busfault_init(void)
 
     act.sa_sigaction = busfault_sigaction;
     act.sa_flags = SA_SIGINFO;
+    sigemptyset(&act.sa_mask);
     if (sigaction(SIGBUS, &act, &old_act) < 0)
         return FALSE;
     previous_busfault_sigaction = old_act.sa_sigaction;
commit 19e5a13970ad9d440c0789395e94931429ef4fbb
Author: YunQiang Su <wzssyqa at gmail.com>
Date:   Sat Oct 12 13:22:35 2013 +0800

    Fix hw/xfree86/common/compiler.h for mips64
    
    Mark mips64 as 64bit
    Use long as PORT_SIZE
    
    Signed-off-by: YunQiang Su <wzssyqa at gmail.com>
    Reviewed-by: Matt Turner <mattst88 at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h
index 3a57186..fb95f58 100644
--- a/hw/xfree86/common/compiler.h
+++ b/hw/xfree86/common/compiler.h
@@ -103,6 +103,7 @@
 #if !defined(__sparc__) && !defined(__sparc) && !defined(__arm32__) && !defined(__nds32__) \
       && !(defined(__alpha__) && defined(linux)) \
       && !(defined(__ia64__) && defined(linux)) \
+      && !(defined(__mips64) && defined(linux)) \
 
 extern _X_EXPORT void outb(unsigned short, unsigned char);
 extern _X_EXPORT void outw(unsigned short, unsigned short);
@@ -721,7 +722,7 @@ xf86WriteMmio32LeNB(__volatile__ void *base, const unsigned long offset,
 }
 
 #elif defined(__mips__) || (defined(__arm32__) && !defined(__linux__))
-#ifdef __arm32__
+#if defined(__arm32__) || defined(__mips64)
 #define PORT_SIZE long
 #else
 #define PORT_SIZE short
commit f466fb2432292d74123d701764c432d3aa75ef1d
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Apr 10 11:45:37 2014 -0400

    xres: Fix size estimation for <8bpp pixmaps (#69057)
    
    Just use floats, it's not like this is a performance path.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/xres.c b/Xext/xres.c
index b26cbb5..546b942 100644
--- a/Xext/xres.c
+++ b/Xext/xres.c
@@ -353,9 +353,9 @@ static unsigned long
 ResGetApproxPixmapBytes(PixmapPtr pix)
 {
     unsigned long nPixels;
-    int bytesPerPixel;
+    float bytesPerPixel;
 
-    bytesPerPixel = pix->drawable.bitsPerPixel >> 3;
+    bytesPerPixel = (float)pix->drawable.bitsPerPixel / 8.0;
     nPixels = pix->drawable.width * pix->drawable.height;
 
     /* Divide by refcnt as pixmap could be shared between clients,  
commit 5df66822c9f6bac1ed3952971958068600ccd095
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Apr 21 21:38:28 2014 -0700

    shadowfb: Fix compilation errors
    
    Ok, that's embarassing -- I didn't even make sure Adam's patch
    compiled. These are minimal fixes to make it build.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/shadowfb/shadow.c b/hw/xfree86/shadowfb/shadow.c
index 7412213..10f72cc 100644
--- a/hw/xfree86/shadowfb/shadow.c
+++ b/hw/xfree86/shadowfb/shadow.c
@@ -36,6 +36,7 @@ typedef struct {
     RefreshAreaFuncPtr preRefresh;
     RefreshAreaFuncPtr postRefresh;
     CloseScreenProcPtr CloseScreen;
+    CreateScreenResourcesProcPtr CreateScreenResources;
 } ShadowScreenRec, *ShadowScreenPtr;
 
 static DevPrivateKeyRec ShadowScreenKeyRec;
@@ -43,7 +44,7 @@ static DevPrivateKeyRec ShadowScreenKeyRec;
 static ShadowScreenPtr
 shadowfbGetScreenPrivate(ScreenPtr pScreen)
 {
-    return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec)
+    return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec);
 }
 
 Bool
@@ -53,7 +54,6 @@ ShadowFBInit2(ScreenPtr pScreen,
 {
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     ShadowScreenPtr pPriv;
-    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
 
     if (!preRefreshArea && !postRefreshArea)
         return FALSE;
@@ -69,7 +69,6 @@ ShadowFBInit2(ScreenPtr pScreen,
     pPriv->pScrn = pScrn;
     pPriv->preRefresh = preRefreshArea;
     pPriv->postRefresh = postRefreshArea;
-    pPriv->vtSema = TRUE;
 
     pPriv->CloseScreen = pScreen->CloseScreen;
     pPriv->CreateScreenResources = pScreen->CreateScreenResources;
@@ -125,7 +124,7 @@ ShadowCreateScreenResources(ScreenPtr pScreen)
     ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 
     pScreen->CreateScreenResources = pPriv->CreateScreenResources;
-    ret = pScreen->CreateScreenResources(pWin);
+    ret = pScreen->CreateScreenResources(pScreen);
     pPriv->CreateScreenResources = pScreen->CreateScreenResources;
     pScreen->CreateScreenResources = ShadowCreateScreenResources;
 
@@ -162,7 +161,7 @@ ShadowCloseScreen(ScreenPtr pScreen)
     pScreen->CloseScreen = pPriv->CloseScreen;
     pScreen->CreateScreenResources = pPriv->CreateScreenResources;
 
-    free((pointer) pPriv);
+    free(pPriv);
 
     return (*pScreen->CloseScreen) (pScreen);
 }
commit 2dcb1672620ef5f16111517e9e7a98cf97deb678
Author: Adam Jackson <ajax at redhat.com>
Date:   Thu Apr 10 13:42:42 2014 -0400

    shadowfb: Port to miext/damage (#31303, #65547)
    
    Somewhat shocking how much simpler this is, isn't it?  We no longer need
    to wrap the screen or GC or Picture, because damage does it for us,
    which is doubly great since the old shadowfb code didn't wrap _enough_
    things (border updates and Render glyphs, at least).  The only real
    difference now between this and shadow is a) shadow will let you track
    arbitrary pixmaps, and b) shadow's update hook runs off the BlockHandler
    whereas shadowfb is immediate.
    
    Tested on nouveau.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/shadowfb/shadow.c b/hw/xfree86/shadowfb/shadow.c
index 4352939..7412213 100644
--- a/hw/xfree86/shadowfb/shadow.c
+++ b/hw/xfree86/shadowfb/shadow.c
@@ -1,8 +1,8 @@
 /*
    Copyright (C) 1999.  The XFree86 Project Inc.
+   Copyright 2014 Red Hat, Inc.
 
    Written by Mark Vojkovich (mvojkovi at ucsd.edu)
-
    Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan at vmware.com)
 */
 
@@ -29,107 +29,22 @@
 #include "picturestr.h"
 
 static Bool ShadowCloseScreen(ScreenPtr pScreen);
-static void ShadowCopyWindow(WindowPtr pWin,
-                             DDXPointRec ptOldOrg, RegionPtr prgn);
-static Bool ShadowCreateGC(GCPtr pGC);
-
-static Bool ShadowEnterVT(ScrnInfoPtr pScrn);
-static void ShadowLeaveVT(ScrnInfoPtr pScrn);
-
-static void ShadowComposite(CARD8 op,
-                            PicturePtr pSrc,
-                            PicturePtr pMask,
-                            PicturePtr pDst,
-                            INT16 xSrc,
-                            INT16 ySrc,
-                            INT16 xMask,
-                            INT16 yMask,
-                            INT16 xDst,
-                            INT16 yDst, CARD16 width, CARD16 height);
+static Bool ShadowCreateScreenResources(ScreenPtr pScreen);
 
 typedef struct {
     ScrnInfoPtr pScrn;
     RefreshAreaFuncPtr preRefresh;
     RefreshAreaFuncPtr postRefresh;
     CloseScreenProcPtr CloseScreen;
-    CopyWindowProcPtr CopyWindow;
-    CreateGCProcPtr CreateGC;
-    ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
-    CompositeProcPtr Composite;
-    Bool (*EnterVT) (ScrnInfoPtr);
-    void (*LeaveVT) (ScrnInfoPtr);
-    Bool vtSema;
 } ShadowScreenRec, *ShadowScreenPtr;
 
-typedef struct {
-    const GCOps *ops;
-    const GCFuncs *funcs;
-} ShadowGCRec, *ShadowGCPtr;
-
 static DevPrivateKeyRec ShadowScreenKeyRec;
 
-#define ShadowScreenKey (&ShadowScreenKeyRec)
-
-static DevPrivateKeyRec ShadowGCKeyRec;
-
-#define ShadowGCKey (&ShadowGCKeyRec)
-
-#define GET_SCREEN_PRIVATE(pScreen) \
-    (ShadowScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, ShadowScreenKey)
-#define GET_GC_PRIVATE(pGC) \
-    (ShadowGCPtr)dixLookupPrivate(&(pGC)->devPrivates, ShadowGCKey)
-
-#define SHADOW_GC_FUNC_PROLOGUE(pGC)\
-    ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\
-    (pGC)->funcs = pGCPriv->funcs;\
-    if(pGCPriv->ops)\
-        (pGC)->ops = pGCPriv->ops
-
-#define SHADOW_GC_FUNC_EPILOGUE(pGC)\
-    pGCPriv->funcs = (pGC)->funcs;\
-    (pGC)->funcs = &ShadowGCFuncs;\
-    if(pGCPriv->ops) {\
-        pGCPriv->ops = (pGC)->ops;\
-        (pGC)->ops = &ShadowGCOps;\
-    }
-
-#define SHADOW_GC_OP_PROLOGUE(pGC)\
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pGC->pScreen); \
-    ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\
-    const GCFuncs *oldFuncs = pGC->funcs;\
-    pGC->funcs = pGCPriv->funcs;\
-    pGC->ops = pGCPriv->ops
-
-#define SHADOW_GC_OP_EPILOGUE(pGC)\
-    pGCPriv->ops = pGC->ops;\
-    pGC->funcs = oldFuncs;\
-    pGC->ops   = &ShadowGCOps
-
-#define IS_VISIBLE(pWin) (pPriv->vtSema && \
-    (((WindowPtr)pWin)->visibility != VisibilityFullyObscured))
-
-#define TRIM_BOX(box, pGC) { \
-    BoxPtr extents = &pGC->pCompositeClip->extents;\
-    if(box.x1 < extents->x1) box.x1 = extents->x1; \
-    if(box.x2 > extents->x2) box.x2 = extents->x2; \
-    if(box.y1 < extents->y1) box.y1 = extents->y1; \
-    if(box.y2 > extents->y2) box.y2 = extents->y2; \
-    }
-
-#define TRANSLATE_BOX(box, pDraw) { \
-    box.x1 += pDraw->x; \
-    box.x2 += pDraw->x; \
-    box.y1 += pDraw->y; \
-    box.y2 += pDraw->y; \
-    }
-
-#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
-    TRANSLATE_BOX(box, pDraw); \
-    TRIM_BOX(box, pGC); \
-    }
-
-#define BOX_NOT_EMPTY(box) \
-    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+static ShadowScreenPtr
+shadowfbGetScreenPrivate(ScreenPtr pScreen)
+{
+    return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec)
+}
 
 Bool
 ShadowFBInit2(ScreenPtr pScreen,
@@ -146,14 +61,10 @@ ShadowFBInit2(ScreenPtr pScreen,
     if (!dixRegisterPrivateKey(&ShadowScreenKeyRec, PRIVATE_SCREEN, 0))
         return FALSE;
 
-    if (!dixRegisterPrivateKey
-        (&ShadowGCKeyRec, PRIVATE_GC, sizeof(ShadowGCRec)))
-        return FALSE;
-
     if (!(pPriv = (ShadowScreenPtr) malloc(sizeof(ShadowScreenRec))))
         return FALSE;
 
-    dixSetPrivate(&pScreen->devPrivates, ShadowScreenKey, pPriv);
+    dixSetPrivate(&pScreen->devPrivates, &ShadowScreenKeyRec, pPriv);
 
     pPriv->pScrn = pScrn;
     pPriv->preRefresh = preRefreshArea;
@@ -161,24 +72,10 @@ ShadowFBInit2(ScreenPtr pScreen,
     pPriv->vtSema = TRUE;
 
     pPriv->CloseScreen = pScreen->CloseScreen;
-    pPriv->CopyWindow = pScreen->CopyWindow;
-    pPriv->CreateGC = pScreen->CreateGC;
-    pPriv->ModifyPixmapHeader = pScreen->ModifyPixmapHeader;
-
-    pPriv->EnterVT = pScrn->EnterVT;
-    pPriv->LeaveVT = pScrn->LeaveVT;
+    pPriv->CreateScreenResources = pScreen->CreateScreenResources;
 
     pScreen->CloseScreen = ShadowCloseScreen;
-    pScreen->CopyWindow = ShadowCopyWindow;
-    pScreen->CreateGC = ShadowCreateGC;
-
-    pScrn->EnterVT = ShadowEnterVT;
-    pScrn->LeaveVT = ShadowLeaveVT;
-
-    if (ps) {
-        pPriv->Composite = ps->Composite;
-        ps->Composite = ShadowComposite;
-    }
+    pScreen->CreateScreenResources = ShadowCreateScreenResources;
 
     return TRUE;
 }
@@ -189,1451 +86,83 @@ ShadowFBInit(ScreenPtr pScreen, RefreshAreaFuncPtr refreshArea)
     return ShadowFBInit2(pScreen, NULL, refreshArea);
 }
 
-/**********************************************************/
-
-static Bool
-ShadowEnterVT(ScrnInfoPtr pScrn)
-{
-    Bool ret;
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen);
-
-    pScrn->EnterVT = pPriv->EnterVT;
-    ret = (*pPriv->EnterVT) (pScrn);
-    pPriv->EnterVT = pScrn->EnterVT;
-    pScrn->EnterVT = ShadowEnterVT;
-    if (ret) {
-        pPriv->vtSema = TRUE;
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-static void
-ShadowLeaveVT(ScrnInfoPtr pScrn)
-{
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen);
-
-    pPriv->vtSema = FALSE;
-
-    pScrn->LeaveVT = pPriv->LeaveVT;
-    (*pPriv->LeaveVT) (pScrn);
-    pPriv->LeaveVT = pScrn->LeaveVT;
-    pScrn->LeaveVT = ShadowLeaveVT;
-}
-
-/**********************************************************/
-
-static Bool
-ShadowCloseScreen(ScreenPtr pScreen)
-{
-    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
-    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
-
-    pScreen->CloseScreen = pPriv->CloseScreen;
-    pScreen->CopyWindow = pPriv->CopyWindow;
-    pScreen->CreateGC = pPriv->CreateGC;
-    pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader;
-
-    pScrn->EnterVT = pPriv->EnterVT;
-    pScrn->LeaveVT = pPriv->LeaveVT;
-
-    if (ps) {
-        ps->Composite = pPriv->Composite;
-    }
-
-    free((void *) pPriv);
-
-    return (*pScreen->CloseScreen) (pScreen);
-}
+/*
+ * Note that we don't do DamageEmpty, or indeed look at the region inside the
+ * DamagePtr at all.  This is an optimization, believe it or not.  The
+ * incoming RegionPtr is the new damage, and if we were to empty the region
+ * miext/damage would just have to waste time reallocating and re-unioning
+ * it every time, whereas if we leave it around the union gets fast-pathed
+ * away.
+ */
 
 static void
-ShadowCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgn)
+shadowfbReportPre(DamagePtr damage, RegionPtr reg, void *closure)
 {
-    ScreenPtr pScreen = pWin->drawable.pScreen;
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
-    int num = 0;
-    RegionRec rgnDst;
-
-    if (pPriv->vtSema) {
-        RegionNull(&rgnDst);
-        RegionCopy(&rgnDst, prgn);
-
-        RegionTranslate(&rgnDst,
-                        pWin->drawable.x - ptOldOrg.x,
-                        pWin->drawable.y - ptOldOrg.y);
-        RegionIntersect(&rgnDst, &pWin->borderClip, &rgnDst);
-        if ((num = RegionNumRects(&rgnDst))) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, num, RegionRects(&rgnDst));
-        }
-        else {
-            RegionUninit(&rgnDst);
-        }
-    }
+    ShadowScreenPtr pPriv = closure;
 
-    pScreen->CopyWindow = pPriv->CopyWindow;
-    (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn);
-    pScreen->CopyWindow = ShadowCopyWindow;
+    if (!pPriv->pScrn->vtSema)
+        return;
 
-    if (num) {
-        if (pPriv->postRefresh)
-            (*pPriv->postRefresh) (pPriv->pScrn, num, RegionRects(&rgnDst));
-        RegionUninit(&rgnDst);
-    }
+    pPriv->preRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
 }
 
 static void
-ShadowComposite(CARD8 op,
-                PicturePtr pSrc,
-                PicturePtr pMask,
-                PicturePtr pDst,
-                INT16 xSrc,
-                INT16 ySrc,
-                INT16 xMask,
-                INT16 yMask,
-                INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+shadowfbReportPost(DamagePtr damage, RegionPtr reg, void *closure)
 {
-    ScreenPtr pScreen = pDst->pDrawable->pScreen;
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
-    PictureScreenPtr ps = GetPictureScreen(pScreen);
-    BoxRec box;
-    BoxPtr extents;
-    Bool boxNotEmpty = FALSE;
-
-    if (pPriv->vtSema && pDst->pDrawable->type == DRAWABLE_WINDOW) {
-
-        box.x1 = pDst->pDrawable->x + xDst;
-        box.y1 = pDst->pDrawable->y + yDst;
-        box.x2 = box.x1 + width;
-        box.y2 = box.y1 + height;
-
-        extents = &pDst->pCompositeClip->extents;
-        if (box.x1 < extents->x1)
-            box.x1 = extents->x1;
-        if (box.x2 > extents->x2)
-            box.x2 = extents->x2;
-        if (box.y1 < extents->y1)
-            box.y1 = extents->y1;
-        if (box.y2 > extents->y2)
-            box.y2 = extents->y2;
-
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
+    ShadowScreenPtr pPriv = closure;
 
-    ps->Composite = pPriv->Composite;
-    (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc,
-                      xMask, yMask, xDst, yDst, width, height);
-    ps->Composite = ShadowComposite;
+    if (!pPriv->pScrn->vtSema)
+        return;
 
-    if (pPriv->postRefresh && boxNotEmpty) {
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-    }
+    pPriv->postRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
 }
 
-/**********************************************************/
-
-static void ShadowValidateGC(GCPtr, unsigned long, DrawablePtr);
-static void ShadowChangeGC(GCPtr, unsigned long);
-static void ShadowCopyGC(GCPtr, unsigned long, GCPtr);
-static void ShadowDestroyGC(GCPtr);
-static void ShadowChangeClip(GCPtr, int, void *, int);
-static void ShadowDestroyClip(GCPtr);
-static void ShadowCopyClip(GCPtr, GCPtr);
-
-GCFuncs ShadowGCFuncs = {
-    ShadowValidateGC, ShadowChangeGC, ShadowCopyGC, ShadowDestroyGC,
-    ShadowChangeClip, ShadowDestroyClip, ShadowCopyClip
-};
-
-extern GCOps ShadowGCOps;
-
 static Bool
-ShadowCreateGC(GCPtr pGC)
+ShadowCreateScreenResources(ScreenPtr pScreen)
 {
-    ScreenPtr pScreen = pGC->pScreen;
-    ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen);
-    ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);
     Bool ret;
+    WindowPtr pWin = pScreen->root;
+    ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 
-    pScreen->CreateGC = pPriv->CreateGC;
-    if ((ret = (*pScreen->CreateGC) (pGC))) {
-        pGCPriv->ops = NULL;
-        pGCPriv->funcs = pGC->funcs;
-        pGC->funcs = &ShadowGCFuncs;
-    }
-    pScreen->CreateGC = ShadowCreateGC;
-
-    return ret;
-}
-
-static void
-ShadowValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pGC);
-    (*pGC->funcs->ValidateGC) (pGC, changes, pDraw);
-    if (pDraw->type == DRAWABLE_WINDOW)
-        pGCPriv->ops = pGC->ops;        /* just so it's not NULL */
-    else
-        pGCPriv->ops = NULL;
-    SHADOW_GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-ShadowDestroyGC(GCPtr pGC)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pGC);
-    (*pGC->funcs->DestroyGC) (pGC);
-    SHADOW_GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-ShadowChangeGC(GCPtr pGC, unsigned long mask)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pGC);
-    (*pGC->funcs->ChangeGC) (pGC, mask);
-    SHADOW_GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-ShadowCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pGCDst);
-    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
-    SHADOW_GC_FUNC_EPILOGUE(pGCDst);
-}
-
-static void
-ShadowChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pGC);
-    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
-    SHADOW_GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-ShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pgcDst);
-    (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
-    SHADOW_GC_FUNC_EPILOGUE(pgcDst);
-}
-
-static void
-ShadowDestroyClip(GCPtr pGC)
-{
-    SHADOW_GC_FUNC_PROLOGUE(pGC);
-    (*pGC->funcs->DestroyClip) (pGC);
-    SHADOW_GC_FUNC_EPILOGUE(pGC);
-}
-
-/**********************************************************/
-
-static void
-ShadowFillSpans(DrawablePtr pDraw,
-                GC * pGC,
-                int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted)
-{
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nInit) {
-        DDXPointPtr ppt = pptInit;
-        int *pwidth = pwidthInit;
-        int i = nInit;
-        BoxRec box;
-        Bool boxNotEmpty = FALSE;
-
-        box.x1 = ppt->x;
-        box.x2 = box.x1 + *pwidth;
-        box.y2 = box.y1 = ppt->y;
+    pScreen->CreateScreenResources = pPriv->CreateScreenResources;
+    ret = pScreen->CreateScreenResources(pWin);
+    pPriv->CreateScreenResources = pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = ShadowCreateScreenResources;
 
-        while (--i) {
-            ppt++;
-            pwidth++;
-            if (box.x1 > ppt->x)
-                box.x1 = ppt->x;
-            if (box.x2 < (ppt->x + *pwidth))
-                box.x2 = ppt->x + *pwidth;
-            if (box.y1 > ppt->y)
-                box.y1 = ppt->y;
-            else if (box.y2 < ppt->y)
-                box.y2 = ppt->y;
-        }
-
-        box.y2++;
-
-        if (!pGC->miTranslate) {
-            TRANSLATE_BOX(box, pDraw);
-        }
-        TRIM_BOX(box, pGC);
-
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-
-        (*pGC->ops->FillSpans) (pDraw, pGC, nInit, pptInit, pwidthInit,
-                                fSorted);
-
-        if (boxNotEmpty && pPriv->postRefresh)
-            (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-    }
-    else
-        (*pGC->ops->FillSpans) (pDraw, pGC, nInit, pptInit, pwidthInit,
-                                fSorted);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowSetSpans(DrawablePtr pDraw,
-               GCPtr pGC,
-               char *pcharsrc,
-               DDXPointPtr pptInit, int *pwidthInit, int nspans, int fSorted)
-{
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nspans) {
-        DDXPointPtr ppt = pptInit;
-        int *pwidth = pwidthInit;
-        int i = nspans;
-        BoxRec box;
-        Bool boxNotEmpty = FALSE;
-
-        box.x1 = ppt->x;
-        box.x2 = box.x1 + *pwidth;
-        box.y2 = box.y1 = ppt->y;
-
-        while (--i) {
-            ppt++;
-            pwidth++;
-            if (box.x1 > ppt->x)
-                box.x1 = ppt->x;
-            if (box.x2 < (ppt->x + *pwidth))
-                box.x2 = ppt->x + *pwidth;
-            if (box.y1 > ppt->y)
-                box.y1 = ppt->y;
-            else if (box.y2 < ppt->y)
-                box.y2 = ppt->y;
-        }
-
-        box.y2++;
-
-        if (!pGC->miTranslate) {
-            TRANSLATE_BOX(box, pDraw);
-        }
-        TRIM_BOX(box, pGC);
-
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-
-        (*pGC->ops->SetSpans) (pDraw, pGC, pcharsrc, pptInit,
-                               pwidthInit, nspans, fSorted);
-
-        if (boxNotEmpty && pPriv->postRefresh)
-            (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-    }
-    else
-        (*pGC->ops->SetSpans) (pDraw, pGC, pcharsrc, pptInit,
-                               pwidthInit, nspans, fSorted);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPutImage(DrawablePtr pDraw,
-               GCPtr pGC,
-               int depth,
-               int x, int y, int w, int h,
-               int leftPad, int format, char *pImage)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw)) {
-        box.x1 = x + pDraw->x;
-        box.x2 = box.x1 + w;
-        box.y1 = y + pDraw->y;
-        box.y2 = box.y1 + h;
+    /* this might look like it leaks, but the damage code reaps listeners
+     * when their drawable disappears.
+     */
+    if (ret) {
+        DamagePtr damage;
 
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
+        if (pPriv->preRefresh) {
+            damage = DamageCreate(shadowfbReportPre, NULL,
+                                  DamageReportRawRegion,
+                                  TRUE, pScreen, pPriv);
+            DamageRegister(&pWin->drawable, damage);
         }
-    }
-
-    (*pGC->ops->PutImage) (pDraw, pGC, depth, x, y, w, h,
-                           leftPad, format, pImage);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
-}
-
-static RegionPtr
-ShadowCopyArea(DrawablePtr pSrc,
-               DrawablePtr pDst,
-               GC * pGC,
-               int srcx, int srcy, int width, int height, int dstx, int dsty)
-{
-    RegionPtr ret;
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDst)) {
-        box.x1 = dstx + pDst->x;
-        box.x2 = box.x1 + width;
-        box.y1 = dsty + pDst->y;
-        box.y2 = box.y1 + height;
 
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
+        if (pPriv->postRefresh) {
+            damage = DamageCreate(shadowfbReportPost, NULL,
+                                  DamageReportRawRegion,
+                                  TRUE, pScreen, pPriv);
+            DamageSetReportAfterOp(damage, TRUE);
+            DamageRegister(&pWin->drawable, damage);
         }
     }
 
-    ret = (*pGC->ops->CopyArea) (pSrc, pDst,
-                                 pGC, srcx, srcy, width, height, dstx, dsty);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
     return ret;
 }
 
-static RegionPtr
-ShadowCopyPlane(DrawablePtr pSrc,
-                DrawablePtr pDst,
-                GCPtr pGC,
-                int srcx, int srcy,
-                int width, int height,
-                int dstx, int dsty, unsigned long bitPlane)
-{
-    RegionPtr ret;
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDst)) {
-        box.x1 = dstx + pDst->x;
-        box.x2 = box.x1 + width;
-        box.y1 = dsty + pDst->y;
-        box.y2 = box.y1 + height;
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    ret = (*pGC->ops->CopyPlane) (pSrc, pDst,
-                                  pGC, srcx, srcy, width, height, dstx, dsty,
-                                  bitPlane);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
-    return ret;
-}
-
-static void
-ShadowPolyPoint(DrawablePtr pDraw,
-                GCPtr pGC, int mode, int nptInit, xPoint * pptInit)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nptInit) {
-        xPoint *ppt = pptInit;
-        int npt = nptInit;
-
-        box.x2 = box.x1 = pptInit->x;
-        box.y2 = box.y1 = pptInit->y;
-
-        /* this could be slow if the points were spread out */
-
-        while (--npt) {
-            ppt++;
-            if (box.x1 > ppt->x)
-                box.x1 = ppt->x;
-            else if (box.x2 < ppt->x)
-                box.x2 = ppt->x;
-            if (box.y1 > ppt->y)
-                box.y1 = ppt->y;
-            else if (box.y2 < ppt->y)
-                box.y2 = ppt->y;
-        }
-
-        box.x2++;
-        box.y2++;
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->PolyPoint) (pDraw, pGC, mode, nptInit, pptInit);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPolylines(DrawablePtr pDraw,
-                GCPtr pGC, int mode, int nptInit, DDXPointPtr pptInit)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nptInit) {
-        DDXPointPtr ppt = pptInit;
-        int npt = nptInit;
-        int extra = pGC->lineWidth >> 1;
-
-        box.x2 = box.x1 = pptInit->x;
-        box.y2 = box.y1 = pptInit->y;
-
-        if (npt > 1) {
-            if (pGC->joinStyle == JoinMiter)
-                extra = 6 * pGC->lineWidth;
-            else if (pGC->capStyle == CapProjecting)
-                extra = pGC->lineWidth;
-        }
-
-        if (mode == CoordModePrevious) {
-            int x = box.x1;
-            int y = box.y1;
-
-            while (--npt) {
-                ppt++;
-                x += ppt->x;
-                y += ppt->y;
-                if (box.x1 > x)
-                    box.x1 = x;
-                else if (box.x2 < x)
-                    box.x2 = x;
-                if (box.y1 > y)
-                    box.y1 = y;
-                else if (box.y2 < y)
-                    box.y2 = y;
-            }
-        }
-        else {
-            while (--npt) {
-                ppt++;
-                if (box.x1 > ppt->x)
-                    box.x1 = ppt->x;
-                else if (box.x2 < ppt->x)
-                    box.x2 = ppt->x;
-                if (box.y1 > ppt->y)
-                    box.y1 = ppt->y;
-                else if (box.y2 < ppt->y)
-                    box.y2 = ppt->y;
-            }
-        }
-
-        box.x2++;
-        box.y2++;
-
-        if (extra) {
-            box.x1 -= extra;
-            box.x2 += extra;
-            box.y1 -= extra;
-            box.y2 += extra;
-        }
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->Polylines) (pDraw, pGC, mode, nptInit, pptInit);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPolySegment(DrawablePtr pDraw,
-                  GCPtr pGC, int nsegInit, xSegment * pSegInit)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nsegInit) {
-        int extra = pGC->lineWidth;
-        xSegment *pSeg = pSegInit;
-        int nseg = nsegInit;
-
-        if (pGC->capStyle != CapProjecting)
-            extra >>= 1;
-
-        if (pSeg->x2 > pSeg->x1) {
-            box.x1 = pSeg->x1;
-            box.x2 = pSeg->x2;
-        }
-        else {
-            box.x2 = pSeg->x1;
-            box.x1 = pSeg->x2;
-        }
-
-        if (pSeg->y2 > pSeg->y1) {
-            box.y1 = pSeg->y1;
-            box.y2 = pSeg->y2;
-        }
-        else {
-            box.y2 = pSeg->y1;
-            box.y1 = pSeg->y2;
-        }
-
-        while (--nseg) {
-            pSeg++;
-            if (pSeg->x2 > pSeg->x1) {
-                if (pSeg->x1 < box.x1)
-                    box.x1 = pSeg->x1;
-                if (pSeg->x2 > box.x2)
-                    box.x2 = pSeg->x2;
-            }
-            else {
-                if (pSeg->x2 < box.x1)
-                    box.x1 = pSeg->x2;
-                if (pSeg->x1 > box.x2)
-                    box.x2 = pSeg->x1;
-            }
-            if (pSeg->y2 > pSeg->y1) {
-                if (pSeg->y1 < box.y1)
-                    box.y1 = pSeg->y1;
-                if (pSeg->y2 > box.y2)
-                    box.y2 = pSeg->y2;
-            }
-            else {
-                if (pSeg->y2 < box.y1)
-                    box.y1 = pSeg->y2;
-                if (pSeg->y1 > box.y2)
-                    box.y2 = pSeg->y1;
-            }
-        }
-
-        box.x2++;
-        box.y2++;
-
-        if (extra) {
-            box.x1 -= extra;
-            box.x2 += extra;
-            box.y1 -= extra;
-            box.y2 += extra;
-        }
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->PolySegment) (pDraw, pGC, nsegInit, pSegInit);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPolyRectangle(DrawablePtr pDraw,
-                    GCPtr pGC, int nRectsInit, xRectangle *pRectsInit)
-{
-    BoxRec box;
-    BoxPtr pBoxInit = NULL;
-    Bool boxNotEmpty = FALSE;
-    int num = 0;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nRectsInit) {
-        xRectangle *pRects = pRectsInit;
-        int nRects = nRectsInit;
-
-        if (nRects >= 32) {
-            int extra = pGC->lineWidth >> 1;
-
-            box.x1 = pRects->x;
-            box.x2 = box.x1 + pRects->width;
-            box.y1 = pRects->y;
-            box.y2 = box.y1 + pRects->height;
-
-            while (--nRects) {
-                pRects++;
-                if (box.x1 > pRects->x)
-                    box.x1 = pRects->x;
-                if (box.x2 < (pRects->x + pRects->width))
-                    box.x2 = pRects->x + pRects->width;
-                if (box.y1 > pRects->y)
-                    box.y1 = pRects->y;
-                if (box.y2 < (pRects->y + pRects->height))
-                    box.y2 = pRects->y + pRects->height;
-            }
-
-            if (extra) {
-                box.x1 -= extra;
-                box.x2 += extra;
-                box.y1 -= extra;
-                box.y2 += extra;
-            }
-
-            box.x2++;
-            box.y2++;
-
-            TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-            if (BOX_NOT_EMPTY(box)) {
-                if (pPriv->preRefresh)
-                    (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-                boxNotEmpty = TRUE;
-            }
-        }
-        else {
-            BoxPtr pbox;
-            int offset1, offset2, offset3;
-
-            offset2 = pGC->lineWidth;
-            if (!offset2)
-                offset2 = 1;
-            offset1 = offset2 >> 1;
-            offset3 = offset2 - offset1;
-
-            pBoxInit = (BoxPtr) malloc(nRects * 4 * sizeof(BoxRec));
-            pbox = pBoxInit;
-
-            while (nRects--) {
-                pbox->x1 = pRects->x - offset1;
-                pbox->y1 = pRects->y - offset1;
-                pbox->x2 = pbox->x1 + pRects->width + offset2;
-                pbox->y2 = pbox->y1 + offset2;
-                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
-                if (BOX_NOT_EMPTY((*pbox))) {
-                    num++;
-                    pbox++;
-                }
-
-                pbox->x1 = pRects->x - offset1;
-                pbox->y1 = pRects->y + offset3;
-                pbox->x2 = pbox->x1 + offset2;
-                pbox->y2 = pbox->y1 + pRects->height - offset2;
-                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
-                if (BOX_NOT_EMPTY((*pbox))) {
-                    num++;
-                    pbox++;
-                }
-
-                pbox->x1 = pRects->x + pRects->width - offset1;
-                pbox->y1 = pRects->y + offset3;
-                pbox->x2 = pbox->x1 + offset2;
-                pbox->y2 = pbox->y1 + pRects->height - offset2;
-                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
-                if (BOX_NOT_EMPTY((*pbox))) {
-                    num++;
-                    pbox++;
-                }
-
-                pbox->x1 = pRects->x - offset1;
-                pbox->y1 = pRects->y + pRects->height - offset1;
-                pbox->x2 = pbox->x1 + pRects->width + offset2;
-                pbox->y2 = pbox->y1 + offset2;
-                TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC);
-                if (BOX_NOT_EMPTY((*pbox))) {
-                    num++;
-                    pbox++;
-                }
-
-                pRects++;
-            }
-
-            if (num) {
-                if (pPriv->preRefresh)
-                    (*pPriv->preRefresh) (pPriv->pScrn, num, pBoxInit);
-            }
-            else {
-                free(pBoxInit);
-            }
-        }
-    }
-
-    (*pGC->ops->PolyRectangle) (pDraw, pGC, nRectsInit, pRectsInit);
-
-    if (boxNotEmpty && pPriv->postRefresh) {
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-    }
-    else if (num) {
-        if (pPriv->postRefresh)
-            (*pPriv->postRefresh) (pPriv->pScrn, num, pBoxInit);
-        free(pBoxInit);
-    }
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
-}
-
-static void
-ShadowPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcsInit, xArc * parcsInit)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && narcsInit) {
-        int narcs = narcsInit;
-        xArc *parcs = parcsInit;
-        int extra = pGC->lineWidth >> 1;
-
-        box.x1 = parcs->x;
-        box.x2 = box.x1 + parcs->width;
-        box.y1 = parcs->y;
-        box.y2 = box.y1 + parcs->height;
-
-        /* should I break these up instead ? */
-
-        while (--narcs) {
-            parcs++;
-            if (box.x1 > parcs->x)
-                box.x1 = parcs->x;
-            if (box.x2 < (parcs->x + parcs->width))
-                box.x2 = parcs->x + parcs->width;
-            if (box.y1 > parcs->y)
-                box.y1 = parcs->y;
-            if (box.y2 < (parcs->y + parcs->height))
-                box.y2 = parcs->y + parcs->height;
-        }
-
-        if (extra) {
-            box.x1 -= extra;
-            box.x2 += extra;
-            box.y1 -= extra;
-            box.y2 += extra;
-        }
-
-        box.x2++;
-        box.y2++;
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->PolyArc) (pDraw, pGC, narcsInit, parcsInit);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
-}
-
-static void
-ShadowFillPolygon(DrawablePtr pDraw,
-                  GCPtr pGC,
-                  int shape, int mode, int count, DDXPointPtr pptInit)
-{
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && (count > 2)) {
-        DDXPointPtr ppt = pptInit;
-        int i = count;
-        BoxRec box;
-        Bool boxNotEmpty = FALSE;
-
-        box.x2 = box.x1 = ppt->x;
-        box.y2 = box.y1 = ppt->y;
-
-        if (mode != CoordModeOrigin) {
-            int x = box.x1;
-            int y = box.y1;
-
-            while (--i) {
-                ppt++;
-                x += ppt->x;
-                y += ppt->y;
-                if (box.x1 > x)
-                    box.x1 = x;
-                else if (box.x2 < x)
-                    box.x2 = x;
-                if (box.y1 > y)
-                    box.y1 = y;
-                else if (box.y2 < y)
-                    box.y2 = y;
-            }
-        }
-        else {
-            while (--i) {
-                ppt++;
-                if (box.x1 > ppt->x)
-                    box.x1 = ppt->x;
-                else if (box.x2 < ppt->x)
-                    box.x2 = ppt->x;
-                if (box.y1 > ppt->y)
-                    box.y1 = ppt->y;
-                else if (box.y2 < ppt->y)
-                    box.y2 = ppt->y;
-            }
-        }
-
-        box.x2++;
-        box.y2++;
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-
-        (*pGC->ops->FillPolygon) (pDraw, pGC, shape, mode, count, pptInit);
-
-        if (boxNotEmpty && pPriv->postRefresh)
-            (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-    }
-    else
-        (*pGC->ops->FillPolygon) (pDraw, pGC, shape, mode, count, pptInit);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPolyFillRect(DrawablePtr pDraw,
-                   GCPtr pGC, int nRectsInit, xRectangle *pRectsInit)
-{
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nRectsInit) {
-        BoxRec box;
-        Bool boxNotEmpty = FALSE;
-        xRectangle *pRects = pRectsInit;
-        int nRects = nRectsInit;
-
-        box.x1 = pRects->x;
-        box.x2 = box.x1 + pRects->width;
-        box.y1 = pRects->y;
-        box.y2 = box.y1 + pRects->height;
-
-        while (--nRects) {
-            pRects++;
-            if (box.x1 > pRects->x)
-                box.x1 = pRects->x;
-            if (box.x2 < (pRects->x + pRects->width))
-                box.x2 = pRects->x + pRects->width;
-            if (box.y1 > pRects->y)
-                box.y1 = pRects->y;
-            if (box.y2 < (pRects->y + pRects->height))
-                box.y2 = pRects->y + pRects->height;
-        }
-
-        /* cfb messes with the pRectsInit so we have to do our
-           calculations first */
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-
-        (*pGC->ops->PolyFillRect) (pDraw, pGC, nRectsInit, pRectsInit);
-
-        if (boxNotEmpty && pPriv->postRefresh)
-            (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-    }
-    else
-        (*pGC->ops->PolyFillRect) (pDraw, pGC, nRectsInit, pRectsInit);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcsInit, xArc * parcsInit)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && narcsInit) {
-        xArc *parcs = parcsInit;
-        int narcs = narcsInit;
-
-        box.x1 = parcs->x;
-        box.x2 = box.x1 + parcs->width;
-        box.y1 = parcs->y;
-        box.y2 = box.y1 + parcs->height;
-
-        /* should I break these up instead ? */
-
-        while (--narcs) {
-            parcs++;
-            if (box.x1 > parcs->x)
-                box.x1 = parcs->x;
-            if (box.x2 < (parcs->x + parcs->width))
-                box.x2 = parcs->x + parcs->width;
-            if (box.y1 > parcs->y)
-                box.y1 = parcs->y;
-            if (box.y2 < (parcs->y + parcs->height))
-                box.y2 = parcs->y + parcs->height;
-        }
-
-        TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->PolyFillArc) (pDraw, pGC, narcsInit, parcsInit);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowTextExtent(FontPtr pFont, int count, char *chars,
-                 FontEncoding fontEncoding, BoxPtr box)
-{
-    unsigned long n, i;
-    int w;
-    CharInfoPtr charinfo[255];  /* encoding only has 1 byte for count */
-
-    GetGlyphs(pFont, (unsigned long) count, (unsigned char *) chars,
-              fontEncoding, &n, charinfo);
-    w = 0;
-    for (i = 0; i < n; i++) {
-        w += charinfo[i]->metrics.characterWidth;
-    }
-    if (i) {
-        w += charinfo[i - 1]->metrics.rightSideBearing;
-    }
-
-    box->x1 = 0;
-    if (n) {
-        if (charinfo[0]->metrics.leftSideBearing < 0) {
-            box->x1 = charinfo[0]->metrics.leftSideBearing;
-        }
-    }
-    box->x2 = w;
-    box->y1 = -FONTMAXBOUNDS(pFont, ascent);
-    box->y2 = FONTMAXBOUNDS(pFont, descent);
-}
-
-static void
-ShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y,
-                int count, char *chars, int wide)
-{
-    FontPtr pFont;
-
-    pFont = pGC->font;
-    if (pFont->info.constantWidth) {
-        int ascent, descent, left, right = 0;
-
-        ascent = max(pFont->info.fontAscent, pFont->info.maxbounds.ascent);
-        descent = max(pFont->info.fontDescent, pFont->info.maxbounds.descent);
-        left = pFont->info.maxbounds.leftSideBearing;
-        if (count > 0) {
-            right = (count - 1) * pFont->info.maxbounds.characterWidth;
-        }
-        right += pFont->info.maxbounds.rightSideBearing;
-        BB->x1 =
-            max(pDrawable->x + x - left,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->x1);
-        BB->y1 =
-            max(pDrawable->y + y - ascent,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->y1);
-        BB->x2 =
-            min(pDrawable->x + x + right,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->x2);
-        BB->y2 =
-            min(pDrawable->y + y + descent,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->y2);
-    }
-    else {
-        ShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0)
-                         ? Linear16Bit : TwoD16Bit : Linear8Bit, BB);
-        BB->x1 =
-            max(pDrawable->x + x + BB->x1,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->x1);
-        BB->y1 =
-            max(pDrawable->y + y + BB->y1,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->y1);
-        BB->x2 =
-            min(pDrawable->x + x + BB->x2,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->x2);
-        BB->y2 =
-            min(pDrawable->y + y + BB->y2,
-                RegionExtents(&((WindowPtr) pDrawable)->winSize)->y2);
-    }
-}
-
-static int
-ShadowPolyText8(DrawablePtr pDraw,
-                GCPtr pGC, int x, int y, int count, char *chars)
-{
-    int width;
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw)) {
-        ShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0);
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    width = (*pGC->ops->PolyText8) (pDraw, pGC, x, y, count, chars);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
-    return width;
-}
-
-static int
-ShadowPolyText16(DrawablePtr pDraw,
-                 GCPtr pGC, int x, int y, int count, unsigned short *chars)
-{
-    int width;
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw)) {
-        ShadowFontToBox(&box, pDraw, pGC, x, y, count, (char *) chars, 1);
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    width = (*pGC->ops->PolyText16) (pDraw, pGC, x, y, count, chars);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-
-    return width;
-}
-
-static void
-ShadowImageText8(DrawablePtr pDraw,
-                 GCPtr pGC, int x, int y, int count, char *chars)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && count) {
-        int top, bot, Min, Max;
-
-        top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
-        bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
-        Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
-        if (Min > 0)
-            Min = 0;
-        Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
-        if (Max < 0)
-            Max = 0;
-
-        /* ugh */
-        box.x1 = pDraw->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing);
-        box.x2 = pDraw->x + x + Max +
-            FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
-        box.y1 = pDraw->y + y - top;
-        box.y2 = pDraw->y + y + bot;
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->ImageText8) (pDraw, pGC, x, y, count, chars);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowImageText16(DrawablePtr pDraw,
-                  GCPtr pGC, int x, int y, int count, unsigned short *chars)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && count) {
-        int top, bot, Min, Max;
-
-        top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
-        bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
-        Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
-        if (Min > 0)
-            Min = 0;
-        Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
-        if (Max < 0)
-            Max = 0;
-
-        /* ugh */
-        box.x1 = pDraw->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing);
-        box.x2 = pDraw->x + x + Max +
-            FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
-        box.y1 = pDraw->y + y - top;
-        box.y2 = pDraw->y + y + bot;
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->ImageText16) (pDraw, pGC, x, y, count, chars);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowImageGlyphBlt(DrawablePtr pDraw,
-                    GCPtr pGC,
-                    int x, int y,
-                    unsigned int nglyphInit,
-                    CharInfoPtr * ppciInit, void *pglyphBase)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nglyphInit) {
-        CharInfoPtr *ppci = ppciInit;
-        unsigned int nglyph = nglyphInit;
-        int top, bot, width = 0;
-
-        top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
-        bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
-        box.x1 = ppci[0]->metrics.leftSideBearing;
-        if (box.x1 > 0)
-            box.x1 = 0;
-        box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
-            ppci[nglyph - 1]->metrics.characterWidth;
-        if (box.x2 < 0)
-            box.x2 = 0;
-
-        box.x2 += pDraw->x + x;
-        box.x1 += pDraw->x + x;
-
-        while (nglyph--) {
-            width += (*ppci)->metrics.characterWidth;
-            ppci++;
-        }
-
-        if (width > 0)
-            box.x2 += width;
-        else
-            box.x1 += width;
-
-        box.y1 = pDraw->y + y - top;
-        box.y2 = pDraw->y + y + bot;
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->ImageGlyphBlt) (pDraw, pGC, x, y, nglyphInit,
-                                ppciInit, pglyphBase);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPolyGlyphBlt(DrawablePtr pDraw,
-                   GCPtr pGC,
-                   int x, int y,
-                   unsigned int nglyphInit,
-                   CharInfoPtr * ppciInit, void *pglyphBase)
-{
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw) && nglyphInit) {
-        CharInfoPtr *ppci = ppciInit;
-        unsigned int nglyph = nglyphInit;
-
-        /* ugh */
-        box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
-        box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
-
-        if (nglyph > 1) {
-            int width = 0;
-
-            while (--nglyph) {
-                width += (*ppci)->metrics.characterWidth;
-                ppci++;
-            }
-
-            if (width > 0)
-                box.x2 += width;
-            else
-                box.x1 += width;
-        }
-
-        box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
-        box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->PolyGlyphBlt) (pDraw, pGC, x, y, nglyphInit,
-                               ppciInit, pglyphBase);
-
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
-
-    SHADOW_GC_OP_EPILOGUE(pGC);
-}
-
-static void
-ShadowPushPixels(GCPtr pGC,
-                 PixmapPtr pBitMap,
-                 DrawablePtr pDraw, int dx, int dy, int xOrg, int yOrg)
+static Bool
+ShadowCloseScreen(ScreenPtr pScreen)
 {
-    BoxRec box;
-    Bool boxNotEmpty = FALSE;
-
-    SHADOW_GC_OP_PROLOGUE(pGC);
-
-    if (IS_VISIBLE(pDraw)) {
-        box.x1 = xOrg;
-        box.y1 = yOrg;
-
-        if (!pGC->miTranslate) {
-            box.x1 += pDraw->x;
-            box.y1 += pDraw->y;
-        }
+    ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 
-        box.x2 = box.x1 + dx;
-        box.y2 = box.y1 + dy;
-
-        TRIM_BOX(box, pGC);
-        if (BOX_NOT_EMPTY(box)) {
-            if (pPriv->preRefresh)
-                (*pPriv->preRefresh) (pPriv->pScrn, 1, &box);
-            boxNotEmpty = TRUE;
-        }
-    }
-
-    (*pGC->ops->PushPixels) (pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
+    pScreen->CloseScreen = pPriv->CloseScreen;
+    pScreen->CreateScreenResources = pPriv->CreateScreenResources;
 
-    if (boxNotEmpty && pPriv->postRefresh)
-        (*pPriv->postRefresh) (pPriv->pScrn, 1, &box);
+    free((pointer) pPriv);
 
-    SHADOW_GC_OP_EPILOGUE(pGC);
+    return (*pScreen->CloseScreen) (pScreen);
 }
-
-GCOps ShadowGCOps = {
-    ShadowFillSpans, ShadowSetSpans,
-    ShadowPutImage, ShadowCopyArea,
-    ShadowCopyPlane, ShadowPolyPoint,
-    ShadowPolylines, ShadowPolySegment,
-    ShadowPolyRectangle, ShadowPolyArc,
-    ShadowFillPolygon, ShadowPolyFillRect,
-    ShadowPolyFillArc, ShadowPolyText8,
-    ShadowPolyText16, ShadowImageText8,
-    ShadowImageText16, ShadowImageGlyphBlt,
-    ShadowPolyGlyphBlt, ShadowPushPixels,
-};
commit 8edeac202ecbace859b7889dd811424471dcca73
Author: Peter Harris <pharris at opentext.com>
Date:   Wed Apr 16 20:24:34 2014 -0400

    composite: Fix memory leak in compCopyWindow
    
    Signed-off-by: Peter Harris <pharris at opentext.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/composite/compwindow.c b/composite/compwindow.c
index 8824294..9a6b2da 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -525,6 +525,7 @@ compCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
                 }
                 FreeScratchGC(pGC);
             }
+            RegionUninit(&rgnDst);
             return;
         }
         dx = pPixmap->screen_x - cw->oldx;
commit 935ea0d7b5e18ad8f22ee074a08cbdc7390d0f5d
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon Apr 21 15:18:45 2014 -0700

    dmxConfigCanvasUpdate: Delay dereference until after checking for NULL
    
    Flagged by cppcheck 1.64:
    [hw/dmx/config/xdmxconfig.c:306] -> [hw/dmx/config/xdmxconfig.c:323]:
     (warning) Possible null pointer dereference: fs - otherwise
               it is redundant to check it against null.
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/dmx/config/xdmxconfig.c b/hw/dmx/config/xdmxconfig.c
index 2b7b968..0540d01 100644
--- a/hw/dmx/config/xdmxconfig.c
+++ b/hw/dmx/config/xdmxconfig.c
@@ -303,7 +303,6 @@ dmxConfigCanvasUpdate(void)
     fs = XQueryFont(dpy, gcontext);
     for (pt = dmxConfigCurrent->subentry; pt; pt = pt->next) {
         int x, y, len;
-        int xo = 3, yo = fs->ascent + fs->descent + 2;
         GC gc;
 
         if (pt->type != dmxConfigDisplay)
@@ -321,6 +320,8 @@ dmxConfigCanvasUpdate(void)
             y = dmxConfigWidgetHeight - 1;
         XDrawRectangle(dpy, win, gc, x, y, w, h);
         if (fs && len) {
+            int xo = 3, yo = fs->ascent + fs->descent + 2;
+
             while (len && XTextWidth(fs, pt->display->name, len) >= w - 2 * xo)
                 --len;
             if (len)
commit 983e30361f49a67252d0b5d82630e70724d69dbf
Author: Peter Harris <pharris at opentext.com>
Date:   Fri Apr 11 17:44:59 2014 -0400

    fb: Fix origin of source picture in fbGlyphs
    
    If a source picture doesn't repeat and a mask format is specified, the
    incorrect calulation of the origin of the glyphs caused the glyphs to
    not be drawn at all.
    
    Noticed when running gtk-demo from RHEL 6.5 and selecting "Rotated
    Text".
    
    Signed-off-by: Peter Harris <pharris at opentext.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>
    
    /* Test for this bug
    
    cc -std=c99 -o glyph glyph.c `pkg-config --cflags --libs xcb-render`
    
    */
    
    // 16 x 16 pictfmt_a8 "glyph"
    static const char glyph[] = {
        0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff,
        0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0,
        0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0,
        0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0,
        0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0xff, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0xff, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0,
        0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0,
        0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0,
        0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0,
        0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff,
    };
    
    static struct {
        uint8_t len;
        uint8_t pad[3];
        uint16_t deltax, deltay;
        uint8_t glyph;
        uint8_t pad2[3];
    } elt = { len:1, glyph:1, deltax:WIN_SIZE/2 - GLYPH_SIZE/2, deltay:WIN_SIZE/2 - GLYPH_SIZE/2 };
    
    int main(int argc, char *argv[])
    {
        int screen;
        xcb_connection_t *c = xcb_connect(NULL, &screen);
        if (!c || xcb_connection_has_error(c)) {
    	fprintf(stderr, "Cannot open default display \"%s\"\n", getenv("DISPLAY"));
    	return EXIT_FAILURE;
        }
    
        // Find root window and depth
        const xcb_setup_t *setup = xcb_get_setup(c);
        if (screen >= setup->roots_len)
    	screen = 0;
        xcb_screen_iterator_t si = xcb_setup_roots_iterator(setup);
        for (int i=0; i < screen; i++)
    	xcb_screen_next(&si);
        xcb_window_t root = si.data->root;
        uint8_t depth = si.data->root_depth;
        xcb_visualid_t visual = si.data->root_visual;
    
        // Find picture formats
        xcb_render_query_pict_formats_reply_t *qpf;
        qpf = xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats(c), NULL);
        if (!qpf) {
    	fprintf(stderr, "Cannot query RENDER picture formats\n");
    	return EXIT_FAILURE;
        }
        xcb_render_pictformat_t fmt_a8 = 0;
        xcb_render_pictforminfo_iterator_t pfi =
            xcb_render_query_pict_formats_formats_iterator(qpf);
        for (int i = 0; i < xcb_render_query_pict_formats_formats_length(qpf); i++) {
    
            if (pfi.data->depth == 8 &&
                    pfi.data->type == XCB_RENDER_PICT_TYPE_DIRECT &&
                    pfi.data->direct.alpha_mask == 0xFF) {
                fmt_a8 = pfi.data->id;
                break;
            }
            xcb_render_pictforminfo_next(&pfi);
        }
        if (!fmt_a8) {
    	fprintf(stderr, "Cannot find a8 RENDER picture format\n");
    	return EXIT_FAILURE;
        }
    
        xcb_render_pictformat_t fmt_visual = 0;
        xcb_render_pictscreen_iterator_t psi =
            xcb_render_query_pict_formats_screens_iterator(qpf);
        for (int i = 0; i < xcb_render_query_pict_formats_screens_length(qpf); i++) {
            xcb_render_pictdepth_iterator_t pdi =
                xcb_render_pictscreen_depths_iterator(psi.data);
            for (int j = 0; i < xcb_render_pictscreen_depths_length(psi.data); i++) {
                xcb_render_pictvisual_iterator_t pvi =
                    xcb_render_pictdepth_visuals_iterator(pdi.data);
                for (int k = 0; k < xcb_render_pictdepth_visuals_length(pdi.data); i++) {
                    if (pvi.data->visual == visual) {
                        fmt_visual = pvi.data->format;
                        goto found_visual;
                    }
                    xcb_render_pictvisual_next(&pvi);
                }
                xcb_render_pictdepth_next(&pdi);
            }
            xcb_render_pictscreen_next(&psi);
        }
    found_visual:
        if (!fmt_visual) {
    	fprintf(stderr, "Cannot find visual RENDER picture format\n");
    	return EXIT_FAILURE;
        }
    
        xcb_render_glyphset_t glyphset = xcb_generate_id(c);
        xcb_render_create_glyph_set(c, glyphset, fmt_a8);
        uint32_t glyph_ids[] = {1};
        xcb_render_add_glyphs(c, glyphset, 1, glyph_ids,
                &(xcb_render_glyphinfo_t){width:GLYPH_SIZE, height:GLYPH_SIZE}, sizeof(glyph), glyph);
    
        // Create window, pixmap, and gc
        xcb_window_t window = xcb_generate_id(c);
        uint32_t list[] = { si.data->black_pixel, XCB_EVENT_MASK_EXPOSURE };
        xcb_create_window(c, XCB_COPY_FROM_PARENT, window, root, 0, 0, WIN_SIZE, WIN_SIZE,
    	    0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT,
    	    XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, list);
        xcb_map_window(c, window);
        xcb_render_picture_t winpic = xcb_generate_id(c);
        xcb_render_create_picture(c, winpic, window, fmt_visual, 0, NULL);
    
        xcb_pixmap_t pixmap = xcb_generate_id(c);
        xcb_create_pixmap(c, depth, pixmap, window, GLYPH_SIZE, GLYPH_SIZE);
        xcb_render_picture_t pixpic = xcb_generate_id(c);
        xcb_render_create_picture(c, pixpic, pixmap, fmt_visual, 0, NULL);
        xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, pixpic,
                (xcb_render_color_t){green:0xFFFF, alpha:0xFFFF}, 1,
                &(xcb_rectangle_t){width:GLYPH_SIZE, height:GLYPH_SIZE} );
    
        xcb_flush(c);
        for (xcb_generic_event_t *ev = xcb_wait_for_event(c); ev; ev = xcb_wait_for_event(c)) {
    	int type = ev->response_type;
    	free(ev);
    	if (type == XCB_EXPOSE) {
                xcb_clear_area(c, 0, window, 0, 0, 0, 0);
                xcb_render_composite_glyphs_8(c, XCB_RENDER_PICT_OP_SRC, pixpic, winpic, fmt_a8,
                        glyphset, 0, 0, sizeof(elt), (uint8_t *)&elt);
                xcb_flush(c);
            }
        }
    
        return EXIT_SUCCESS;
    }

diff --git a/fb/fbpict.c b/fb/fbpict.c
index c2ee8a5..21baf89 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -191,7 +191,7 @@ fbGlyphs(CARD8 op,
 	pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents);
 
 	pixman_composite_glyphs(op, srcImage, dstImage, format,
-				xSrc + srcXoff + xDst, ySrc + srcYoff + yDst,
+				xSrc + srcXoff + extents.x1 - xDst, ySrc + srcYoff + extents.y1 - yDst,
 				extents.x1, extents.y1,
 				extents.x1 + dstXoff, extents.y1 + dstYoff,
 				extents.x2 - extents.x1,


More information about the Xquartz-changes mailing list