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

Jeremy Huddleston jeremyhu at freedesktop.org
Mon Jul 21 22:59:19 PDT 2014


 config/config.c                            |  129 -----
 config/udev.c                              |   10 
 configure.ac                               |   14 
 exa/exa_unaccel.c                          |    2 
 fb/fbscreen.c                              |    3 
 glamor/Makefile.am                         |   16 
 glamor/glamor.c                            |   55 +-
 glamor/glamor.h                            |   23 
 glamor/glamor_copy.c                       |  693 +++++++++++++++++++++++++++++
 glamor/glamor_copyarea.c                   |  626 --------------------------
 glamor/glamor_copyplane.c                  |   75 ---
 glamor/glamor_copywindow.c                 |   56 --
 glamor/glamor_core.c                       |  202 +++-----
 glamor/glamor_dash.c                       |  370 +++++++++++++++
 glamor/glamor_fbo.c                        |    1 
 glamor/glamor_fill.c                       |  356 --------------
 glamor/glamor_font.c                       |    1 
 glamor/glamor_glyphblt.c                   |  154 ++----
 glamor/glamor_glyphs.c                     |   10 
 glamor/glamor_gradient.c                   |   19 
 glamor/glamor_image.c                      |    3 
 glamor/glamor_largepixmap.c                |   13 
 glamor/glamor_lines.c                      |  187 +++++++
 glamor/glamor_picture.c                    |   18 
 glamor/glamor_pixmap.c                     |  510 ---------------------
 glamor/glamor_points.c                     |    3 
 glamor/glamor_polylines.c                  |  136 -----
 glamor/glamor_prepare.c                    |  274 +++++++++++
 glamor/glamor_prepare.h                    |   52 ++
 glamor/glamor_priv.h                       |  266 ++++++-----
 glamor/glamor_program.c                    |   56 +-
 glamor/glamor_program.h                    |    6 
 glamor/glamor_render.c                     |  105 +---
 glamor/glamor_segment.c                    |   44 -
 glamor/glamor_segs.c                       |  188 +++++++
 glamor/glamor_spans.c                      |    3 
 glamor/glamor_sync.c                       |  117 ++++
 glamor/glamor_text.c                       |    6 
 glamor/glamor_tile.c                       |  293 ------------
 glamor/glamor_transfer.c                   |   48 --
 glamor/glamor_transform.c                  |   72 ++-
 glamor/glamor_trapezoid.c                  |   22 
 glamor/glamor_utils.c                      |   79 +++
 glamor/glamor_utils.h                      |  218 ++-------
 glamor/glamor_vbo.c                        |    2 
 glamor/glamor_xv.c                         |  265 +++--------
 hw/kdrive/ephyr/Makefile.am                |    5 
 hw/kdrive/ephyr/ephyr.c                    |   10 
 hw/kdrive/ephyr/ephyr.h                    |   13 
 hw/kdrive/ephyr/ephyr_glamor_glx.c         |   24 -
 hw/kdrive/ephyr/ephyr_glamor_xv.c          |  161 ++++++
 hw/kdrive/ephyr/ephyrinit.c                |   14 
 hw/kdrive/ephyr/ephyrvideo.c               |   34 -
 hw/kdrive/ephyr/hostx.c                    |   34 -
 hw/kdrive/src/kdrive.c                     |    4 
 hw/kdrive/src/kdrive.h                     |    1 
 hw/kdrive/src/kxv.c                        |   81 ---
 hw/kdrive/src/kxv.h                        |   23 
 hw/xfree86/common/xf86AutoConfig.c         |    2 
 hw/xfree86/common/xf86Config.c             |    2 
 hw/xfree86/common/xf86DPMS.c               |    2 
 hw/xfree86/common/xf86VGAarbiterPriv.h     |   10 
 hw/xfree86/common/xf86pciBus.c             |   24 -
 hw/xfree86/common/xf86pciBus.h             |    5 
 hw/xfree86/common/xf86platformBus.c        |  139 +++--
 hw/xfree86/common/xf86platformBus.h        |  104 +++-
 hw/xfree86/common/xf86xv.c                 |   53 --
 hw/xfree86/common/xf86xv.h                 |   36 -
 hw/xfree86/dri2/dri2.c                     |   36 +
 hw/xfree86/glamor_egl/Makefile.am          |    3 
 hw/xfree86/glamor_egl/glamor_xf86_xv.c     |  185 +++++++
 hw/xfree86/man/xorg.conf.man               |   77 +++
 hw/xfree86/modes/xf86Rotate.c              |   18 
 hw/xfree86/os-support/linux/lnx_platform.c |   65 +-
 hw/xfree86/parser/Makefile.am              |    1 
 hw/xfree86/parser/OutputClass.c            |  167 ++++++
 hw/xfree86/parser/configProcs.h            |    5 
 hw/xfree86/parser/read.c                   |    6 
 hw/xfree86/parser/write.c                  |    2 
 hw/xfree86/parser/xf86Parser.h             |    9 
 hw/xwayland/Makefile.am                    |   31 +
 hw/xwayland/drm.xml                        |  182 +++++++
 hw/xwayland/xwayland-glamor.c              |  570 +++++++++++++++++++++++
 hw/xwayland/xwayland.c                     |   38 +
 hw/xwayland/xwayland.h                     |   17 
 hw/xwin/Makefile.am                        |    2 
 include/callback.h                         |   18 
 include/colormap.h                         |   16 
 include/cursor.h                           |    4 
 include/dix.h                              |   69 +-
 include/dixfont.h                          |   10 
 include/dixgrabs.h                         |    4 
 include/gc.h                               |    4 
 include/gcstruct.h                         |   38 -
 include/hotplug.h                          |   67 --
 include/input.h                            |    8 
 include/os.h                               |   52 +-
 include/pixmap.h                           |   14 
 include/property.h                         |   36 -
 include/resource.h                         |   74 +--
 include/scrnintstr.h                       |  116 ++++
 include/servermd.h                         |    9 
 include/window.h                           |   20 
 include/xkbsrv.h                           |   18 
 mi/mi.h                                    |   85 ++-
 mi/miarc.c                                 |   11 
 mi/mieq.c                                  |    2 
 mi/mifillarc.c                             |  146 ++----
 mi/misprite.c                              |    4 
 mi/miwideline.c                            |   20 
 mi/mizerarc.c                              |    2 
 mi/mizerline.c                             |   16 
 os/access.c                                |    6 
 os/log.c                                   |    2 
 present/present.c                          |   27 -
 115 files changed, 5037 insertions(+), 3857 deletions(-)

New commits:
commit 1faa76670572e3478965fd2cd9ab60ab2d865e3a
Author: Jeremy Huddleston Sequoia <jeremyhu at apple.com>
Date:   Sat Jul 19 17:08:09 2014 -0700

    mieq: Fix a crash regression in mieqProcessDeviceEvent
    
    (lldb) bt
    * thread #6: tid = 0x92d4eb, 0x00000001001dee94 X11.bin`mieqProcessDeviceEvent(dev=0x0000000000000000, event=0x0000000100298bb0,
    screen=0x0000000000000000) + 36 at mieq.c:519, stop reason = EXC_BAD_ACCESS (code=1, address=0x44)
      * frame #0: 0x00000001001dee94 X11.bin`mieqProcessDeviceEvent(dev=0x0000000000000000, event=0x0000000100298bb0, screen=0x0000000000000000) + 36 at
    mieq.c:519
        frame #1: 0x00000001001df3eb X11.bin`mieqProcessInputEvents + 555 at mieq.c:631
        frame #2: 0x0000000100017674 X11.bin`ProcessInputEvents + 20 at darwinEvents.c:422
        frame #3: 0x0000000100175eaa X11.bin`Dispatch + 154 at dispatch.c:357
        frame #4: 0x0000000100181b4a X11.bin`dix_main(argc=4, argv=0x00007fff5fbff750, envp=0x00007fff5fbff650) + 1594 at main.c:296
        frame #5: 0x000000010001ba80 X11.bin`server_thread(arg=0x0000000101208220) + 64 at quartzStartup.c:66
        frame #6: 0x00007fff89bb9899 libsystem_pthread.dylib`_pthread_body + 138
        frame #7: 0x00007fff89bb972a libsystem_pthread.dylib`_pthread_start + 137
        frame #8: 0x00007fff89bbdfc9 libsystem_pthread.dylib`thread_start + 13
    
    Regression from: 9fb08310b51b46736f3ca8dbc04efdf502420403
    
    Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu at apple.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/mi/mieq.c b/mi/mieq.c
index 872ff93..8907a6e 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -516,7 +516,7 @@ mieqProcessDeviceEvent(DeviceIntPtr dev, InternalEvent *event, ScreenPtr screen)
     verify_internal_event(event);
 
     /* refuse events from disabled devices */
-    if (!dev->enabled)
+    if (dev && !dev->enabled)
         return;
 
     /* Custom event handler */
commit cff12936275db2f71f6d24f9ea0985a0d14af454
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Jul 18 21:46:23 2014 -0700

    glamor: sync_fence_set_triggered should use glFlush, not glFinish
    
    I intended to use glFlush all along, but somehow managed to type
    glFinish instead. glFlush is sufficient (for a single-queue GPU) to
    ensure serialization between queued rendering in the X server and
    future rendering from the client.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>

diff --git a/glamor/glamor_sync.c b/glamor/glamor_sync.c
index d3d64a9..5e158c3 100644
--- a/glamor/glamor_sync.c
+++ b/glamor/glamor_sync.c
@@ -53,7 +53,7 @@ glamor_sync_fence_set_triggered (SyncFence *fence)
 
 	/* Flush pending rendering operations */
         glamor_make_current(glamor);
-        glFinish();
+        glFlush();
 
 	fence->funcs.SetTriggered = glamor_fence->set_triggered;
 	fence->funcs.SetTriggered(fence);
commit cfa302d6224d10860e60491333950544c4fb9b04
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Jul 18 11:16:27 2014 -0700

    glamor: Add support for SHM sync fences
    
    This hooks up SHM sync fences to complete the requirements for DRI3
    running on Glamor.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 334d8fc..db72cb1 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -47,6 +47,7 @@ libglamor_la_SOURCES = \
 	glamor_utils.c\
 	glamor_utils.h\
 	glamor_xv.c \
+	glamor_sync.c \
 	glamor.h
 
 libglamor_egl_stubs_la_SOURCES = glamor_egl_stubs.c
diff --git a/glamor/glamor.c b/glamor/glamor.c
index d7b8b09..521bc25 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -519,6 +519,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 #endif
     glamor_pixmap_init(screen);
     glamor_glyphs_init(screen);
+    glamor_sync_init(screen);
 
     glamor_priv->screen = screen;
 
@@ -588,6 +589,7 @@ glamor_close_screen(ScreenPtr screen)
 #endif
     glamor_priv = glamor_get_screen_private(screen);
     flags = glamor_priv->flags;
+    glamor_sync_close(screen);
     glamor_glyphs_fini(screen);
     screen->CloseScreen = glamor_priv->saved_procs.close_screen;
     screen->CreateScreenResources =
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 2a9ecce..57a4687 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -33,6 +33,11 @@
 #include "glamor.h"
 #include "xvdix.h"
 
+#if XSYNC
+#include "misyncshm.h"
+#include "misyncstr.h"
+#endif
+
 #include <epoxy/gl.h>
 #if GLAMOR_HAS_GBM
 #define MESA_EGL_NO_X11_HEADERS
@@ -184,6 +189,9 @@ struct glamor_saved_procs {
     DestroyPictureProcPtr destroy_picture;
     UnrealizeGlyphProcPtr unrealize_glyph;
     SetWindowPixmapProcPtr set_window_pixmap;
+#if XSYNC
+    SyncScreenFuncsRec sync_screen_funcs;
+#endif
 };
 
 #define CACHE_FORMAT_COUNT 3
@@ -978,6 +986,13 @@ void glamor_composite_rectangles(CARD8 op,
                                  xRenderColor *color,
                                  int num_rects, xRectangle *rects);
 
+/* glamor_sync.c */
+Bool
+glamor_sync_init(ScreenPtr screen);
+
+void
+glamor_sync_close(ScreenPtr screen);
+
 /* glamor_util.c */
 void
 glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
diff --git a/glamor/glamor_sync.c b/glamor/glamor_sync.c
new file mode 100644
index 0000000..d3d64a9
--- /dev/null
+++ b/glamor/glamor_sync.c
@@ -0,0 +1,117 @@
+/*
+ * 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 "misyncshm.h"
+#include "misyncstr.h"
+
+#if XSYNC
+/*
+ * This whole file exists to wrap a sync fence trigger operation so
+ * that we can flush GL to provide serialization between the server
+ * and the shm fence client
+ */
+
+static DevPrivateKeyRec glamor_sync_fence_key;
+
+struct glamor_sync_fence {
+        SyncFenceSetTriggeredFunc set_triggered;
+};
+
+static inline struct glamor_sync_fence *
+glamor_get_sync_fence(SyncFence *fence)
+{
+    return (struct glamor_sync_fence *) dixLookupPrivate(&fence->devPrivates, &glamor_sync_fence_key);
+}
+
+static void
+glamor_sync_fence_set_triggered (SyncFence *fence)
+{
+	ScreenPtr screen = fence->pScreen;
+	glamor_screen_private *glamor = glamor_get_screen_private(screen);
+	struct glamor_sync_fence *glamor_fence = glamor_get_sync_fence(fence);
+
+	/* Flush pending rendering operations */
+        glamor_make_current(glamor);
+        glFinish();
+
+	fence->funcs.SetTriggered = glamor_fence->set_triggered;
+	fence->funcs.SetTriggered(fence);
+	glamor_fence->set_triggered = fence->funcs.SetTriggered;
+	fence->funcs.SetTriggered = glamor_sync_fence_set_triggered;
+}
+
+static void
+glamor_sync_create_fence(ScreenPtr screen,
+                        SyncFence *fence,
+                        Bool initially_triggered)
+{
+	glamor_screen_private *glamor = glamor_get_screen_private(screen);
+	SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+	struct glamor_sync_fence *glamor_fence = glamor_get_sync_fence(fence);
+
+	screen_funcs->CreateFence = glamor->saved_procs.sync_screen_funcs.CreateFence;
+	screen_funcs->CreateFence(screen, fence, initially_triggered);
+	glamor->saved_procs.sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
+	screen_funcs->CreateFence = glamor_sync_create_fence;
+
+	glamor_fence->set_triggered = fence->funcs.SetTriggered;
+	fence->funcs.SetTriggered = glamor_sync_fence_set_triggered;
+}
+#endif
+
+Bool
+glamor_sync_init(ScreenPtr screen)
+{
+#if XSYNC
+	glamor_screen_private   *glamor = glamor_get_screen_private(screen);
+	SyncScreenFuncsPtr      screen_funcs;
+
+	if (!dixPrivateKeyRegistered(&glamor_sync_fence_key)) {
+		if (!dixRegisterPrivateKey(&glamor_sync_fence_key,
+					   PRIVATE_SYNC_FENCE,
+					   sizeof (struct glamor_sync_fence)))
+			return FALSE;
+	}
+
+	if (!miSyncShmScreenInit(screen))
+		return FALSE;
+
+	screen_funcs = miSyncGetScreenFuncs(screen);
+	glamor->saved_procs.sync_screen_funcs.CreateFence = screen_funcs->CreateFence;
+	screen_funcs->CreateFence = glamor_sync_create_fence;
+#endif
+	return TRUE;
+}
+
+void
+glamor_sync_close(ScreenPtr screen)
+{
+#if XSYNC
+        glamor_screen_private   *glamor = glamor_get_screen_private(screen);
+        SyncScreenFuncsPtr      screen_funcs = miSyncGetScreenFuncs(screen);
+
+        if (screen_funcs)
+                screen_funcs->CreateFence = glamor->saved_procs.sync_screen_funcs.CreateFence;
+#endif
+}
commit ac3acab1311c47cc73e2681e575f0407284c3c66
Author: Colin Walters <walters at verbum.org>
Date:   Fri Jul 18 09:13:54 2014 -0400

    xf86platformBus: Add assertion to avoid (fatal) compiler warning
    
    Compilation of -video-intel started failing in gnome-continuous,
    it's because xserver has -Werror=return-type on, and gcc can't
    prove this function always returns a value:
    
       /usr/include/xorg/xf86platformBus.h:119:1: error: control reaches end of non-void function [-Werror=return-type]
    
    Let's add assertions to the accessor functions to fix this.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 2a90104..317dd24 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -115,6 +115,9 @@ _xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib
         return xf86_platform_device_odev_attributes(device)->busid;
     case ODEV_ATTRIB_DRIVER:
         return xf86_platform_device_odev_attributes(device)->driver;
+    default:
+        assert(FALSE);
+        return NULL;
     }
 }
 
@@ -135,6 +138,9 @@ _xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int at
         return xf86_platform_device_odev_attributes(device)->major;
     case ODEV_ATTRIB_MINOR:
         return xf86_platform_device_odev_attributes(device)->minor;
+    default:
+        assert(FALSE);
+        return 0;
     }
 }
 
commit 5c2e9fa3d6c4bdf626fededce866056ba8eca502
Merge: e678b49 6d49548
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 17 20:06:21 2014 -0700

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

commit 6d4954884908ea9894fcfe9836db1ba7bb45be61
Merge: 9ddcb20 55f5bfb
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jul 17 18:00:44 2014 -0700

    Merge remote-tracking branch 'origin/master' into glamor-next
    
    I've done this merge manually to resolve the minor conflict in glamor.c.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>

diff --cc glamor/glamor.c
index a82c46f,3588903..d7b8b09
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@@ -407,9 -407,10 +408,14 @@@ glamor_init(ScreenPtr screen, unsigned 
          epoxy_has_gl_extension("GL_ARB_map_buffer_range");
      glamor_priv->has_buffer_storage =
          epoxy_has_gl_extension("GL_ARB_buffer_storage");
 +    glamor_priv->has_nv_texture_barrier =
 +        epoxy_has_gl_extension("GL_NV_texture_barrier");
++
 +    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
+     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
+     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
+     glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]);
+     glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]);
  #ifdef MAX_FBO_SIZE
      glamor_priv->max_fbo_size = MAX_FBO_SIZE;
  #endif
commit 9ddcb20f47b5e199989c8990512b0bca1354af86
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 16 07:24:09 2014 +0100

    glamor: Drop the "are we doing a series of blits or draws" logic.
    
    It's unused since keithp's copy acceleration code completely replaced
    glamor_copyarea.c and removed the blit path.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 5e6003d..a82c46f 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -250,11 +250,6 @@ glamor_block_handler(ScreenPtr screen)
     glamor_priv->tick++;
     glFlush();
     glamor_fbo_expire(glamor_priv);
-    if (glamor_priv->state == RENDER_STATE
-        && glamor_priv->render_idle_cnt++ > RENDER_IDEL_MAX) {
-        glamor_priv->state = IDLE_STATE;
-        glamor_priv->render_idle_cnt = 0;
-    }
 }
 
 static void
diff --git a/glamor/glamor_points.c b/glamor/glamor_points.c
index d4525e2..84383d2 100644
--- a/glamor/glamor_points.c
+++ b/glamor/glamor_points.c
@@ -105,9 +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_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
-
     return TRUE;
 
 bail_ctx:
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index dc4f9b8..2a9ecce 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -194,11 +194,6 @@ struct glamor_saved_procs {
 #define GLAMOR_TICK_AFTER(t0, t1) 	\
 	(((int)(t1) - (int)(t0)) < 0)
 
-#define IDLE_STATE 0
-#define RENDER_STATE 1
-#define BLIT_STATE 2
-#define RENDER_IDEL_MAX 32
-
 typedef struct glamor_screen_private {
     unsigned int tick;
     enum glamor_gl_flavor gl_flavor;
@@ -288,8 +283,6 @@ typedef struct glamor_screen_private {
     char delayed_fallback_string[GLAMOR_DELAYED_STRING_MAX + 1];
     int delayed_fallback_pending;
     int flags;
-    int state;
-    unsigned int render_idle_cnt;
     ScreenPtr screen;
     int dri3_enabled;
 
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index add376f..b212fe1 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1313,8 +1313,6 @@ glamor_composite_with_shader(CARD8 op,
     glDisableVertexAttribArray(GLAMOR_VERTEX_MASK);
     glDisable(GL_BLEND);
     DEBUGF("finish rendering.\n");
-    glamor_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
     if (saved_source_format)
         source->format = saved_source_format;
 
diff --git a/glamor/glamor_text.c b/glamor/glamor_text.c
index 6e02b9a..59cd0fd 100644
--- a/glamor/glamor_text.c
+++ b/glamor/glamor_text.c
@@ -293,9 +293,6 @@ glamor_poly_text(DrawablePtr drawable, GCPtr gc,
 
     glDisable(GL_COLOR_LOGIC_OP);
 
-    glamor_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
-
     *final_pos = x;
     return TRUE;
 
@@ -493,9 +490,6 @@ glamor_image_text(DrawablePtr drawable, GCPtr gc,
     (void) glamor_text(drawable, gc, glamor_font, prog,
                        x, y, count, chars, charinfo, sixteen);
 
-    glamor_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
-
     return TRUE;
 
 bail:
commit b03a581d8cbe3f29140935063b865285e2a00333
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 16 07:15:58 2014 +0100

    glamor: Remove a dead prototype.
    
    The corresponding code was deleted in
    2ff41008494e6c5909c058f1f80b4f66617dada1 (2012)
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 61f393d..dc4f9b8 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -866,12 +866,6 @@ Bool glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
                                           GLenum type, int no_alpha, int revert,
                                           int swap_rb, void *bits);
 
-/**
- * Destroy all the resources allocated on the uploading
- * phase, includs the tex and fbo.
- **/
-void glamor_destroy_upload_pixmap(PixmapPtr pixmap);
-
 int glamor_create_picture(PicturePtr picture);
 
 void glamor_set_window_pixmap(WindowPtr pWindow, PixmapPtr pPixmap);
commit b5f94df319469ad44b0e88374a0d389414803f7a
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 16 07:06:30 2014 +0100

    glamor: Drop dead glamor_restore_pixmap_to_texture().
    
    Unused since the glamor_prepare.c replacement of glamor_finish_access().
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 2275ede..725fa5e 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -1064,13 +1064,6 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
     return ret;
 }
 
-void
-glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
-{
-    if (glamor_upload_pixmap_to_texture(pixmap) != GLAMOR_UPLOAD_DONE)
-        LogMessage(X_WARNING, "Failed to restore pixmap to texture.\n");
-}
-
 /*
  * as gles2 only support a very small set of color format and
  * type when do glReadPixel,
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 17406ab..61f393d 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -789,16 +789,6 @@ void
 glamor_put_vbo_space(ScreenPtr screen);
 
 /**
- * Restore a pixmap's data which is downloaded by
- * glamor_download_pixmap_to_cpu to its original
- * gl texture. Used by glamor_finish_access.
- *
- * The pixmap must originally be a texture -- gl_fbo must be
- * GLAMOR_FBO_NORMAL.
- **/
-void glamor_restore_pixmap_to_texture(PixmapPtr pixmap);
-
-/**
  * According to the flag,
  * if the flag is GLAMOR_CREATE_FBO_NO_FBO then just ensure
  * the fbo has a valid texture. Otherwise, it will ensure
commit 98155bd9d9b2a15a4dbcf80b2b57a7636efb14da
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 16 07:01:28 2014 +0100

    glamor: Drop dead glamor_download_pixmap_to_cpu()
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 00e3827..2275ede 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -923,26 +923,6 @@ glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits,
     }
 }
 
-/*
- * download sub region from a large region.
- */
-static void
-glamor_get_bits(char *dst_bits, int dst_stride, char *src_bits,
-                int src_stride, int bpp, int x, int y, int w, int h)
-{
-    int j;
-    int byte_per_pixel;
-
-    byte_per_pixel = bpp / 8;
-    dst_bits += y * dst_stride + x * byte_per_pixel;
-
-    for (j = y; j < y + h; j++) {
-        memcpy(dst_bits, src_bits, w * byte_per_pixel);
-        src_bits += src_stride;
-        dst_bits += dst_stride;
-    }
-}
-
 Bool
 glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
                                     int h, int stride, void *bits, int pbo)
@@ -1160,300 +1140,6 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
     return temp_fbo;
 }
 
-/*
- * Download a sub region of pixmap to a specified memory region.
- * The pixmap must have a valid FBO, otherwise return a NULL.
- * */
-
-static void *
-_glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
-                                   GLenum type, int no_alpha,
-                                   int revert, int swap_rb,
-                                   int x, int y, int w, int h,
-                                   int stride, void *bits, int pbo,
-                                   glamor_access_t access)
-{
-    glamor_pixmap_private *pixmap_priv;
-    GLenum gl_access = 0, gl_usage = 0;
-    void *data;
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(pixmap->drawable.pScreen);
-    glamor_pixmap_fbo *temp_fbo = NULL;
-    int need_post_conversion = 0;
-    int need_free_data = 0;
-    int fbo_x_off, fbo_y_off;
-
-    data = bits;
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return NULL;
-
-    switch (access) {
-    case GLAMOR_ACCESS_RO:
-        gl_access = GL_READ_ONLY;
-        gl_usage = GL_STREAM_READ;
-        break;
-    case GLAMOR_ACCESS_RW:
-        gl_access = GL_READ_WRITE;
-        gl_usage = GL_DYNAMIC_DRAW;
-        break;
-    default:
-        ErrorF("Glamor: Invalid access code. %d\n", access);
-        assert(0);
-    }
-
-    glamor_make_current(glamor_priv);
-    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
-
-    need_post_conversion = (revert > REVERT_NORMAL);
-    if (need_post_conversion) {
-        if (pixmap->drawable.depth == 1) {
-            int temp_stride;
-
-            temp_stride = (((w * 8 + 7) / 8) + 3) & ~3;
-            data = malloc(temp_stride * h);
-            if (data == NULL)
-                return NULL;
-            need_free_data = 1;
-        }
-    }
-
-    pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
-        && !need_post_conversion
-        && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) {
-        if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, x, y, w, h,
-                                                        format, type, no_alpha,
-                                                        revert, swap_rb))) {
-            free(data);
-            return NULL;
-        }
-        x = 0;
-        y = 0;
-        fbo_x_off = 0;
-        fbo_y_off = 0;
-    }
-
-    glPixelStorei(GL_PACK_ALIGNMENT, 4);
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) {
-        assert(pbo > 0);
-        glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
-        glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, gl_usage);
-    }
-
-    glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) {
-        bits = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
-        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-    }
-
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-    if (need_post_conversion) {
-        /* As OpenGL desktop version never enters here.
-         * Don't need to consider if the pbo is valid.*/
-        bits = glamor_color_convert_to_bits(data, bits,
-                                            w, h,
-                                            stride, no_alpha, revert, swap_rb);
-    }
-
-    if (temp_fbo != NULL)
-        glamor_destroy_fbo(temp_fbo);
-    if (need_free_data)
-        free(data);
-
-    return bits;
-}
-
-void *
-glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w, int h,
-                                  int stride, void *bits, int pbo,
-                                  glamor_access_t access)
-{
-    GLenum format, type;
-    int no_alpha, revert, swap_rb;
-    glamor_pixmap_private *pixmap_priv;
-    Bool force_clip;
-
-    if (glamor_get_tex_format_type_from_pixmap(pixmap,
-                                               &format,
-                                               &type,
-                                               &no_alpha,
-                                               &revert, &swap_rb, 0)) {
-        glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
-        return NULL;
-    }
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return NULL;
-
-    force_clip = pixmap_priv->base.glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP
-        && !glamor_check_fbo_size(pixmap_priv->base.glamor_priv, w, h);
-
-    if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE || force_clip) {
-
-        RegionRec region;
-        BoxRec box;
-        int n_region;
-        glamor_pixmap_clipped_regions *clipped_regions;
-        void *sub_bits;
-        int i, j;
-
-        sub_bits = malloc(h * stride);
-        if (sub_bits == NULL)
-            return FALSE;
-        box.x1 = x;
-        box.y1 = y;
-        box.x2 = x + w;
-        box.y2 = y + h;
-        RegionInitBoxes(&region, &box, 1);
-
-        if (!force_clip)
-            clipped_regions =
-                glamor_compute_clipped_regions(pixmap_priv, &region, &n_region,
-                                               0, 0, 0);
-        else
-            clipped_regions =
-                glamor_compute_clipped_regions_ext(pixmap_priv, &region,
-                                                   &n_region,
-                                                   pixmap_priv->large.block_w,
-                                                   pixmap_priv->large.block_h,
-                                                   0,
-                                                   0);
-
-        DEBUGF("start download large pixmap %p %dx%d \n", pixmap, w, h);
-        for (i = 0; i < n_region; i++) {
-            BoxPtr boxes;
-            int nbox;
-            int temp_stride;
-            void *temp_bits;
-
-            assert(pbo == 0);
-            SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
-
-            boxes = RegionRects(clipped_regions[i].region);
-            nbox = RegionNumRects(clipped_regions[i].region);
-            for (j = 0; j < nbox; j++) {
-                temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
-                                            pixmap->drawable.depth);
-
-                if (boxes[j].x1 == x && temp_stride == stride) {
-                    temp_bits = (char *) bits + (boxes[j].y1 - y) * stride;
-                }
-                else {
-                    temp_bits = sub_bits;
-                }
-                DEBUGF("download x %d y %d w %d h %d temp stride %d \n",
-                       boxes[j].x1, boxes[j].y1,
-                       boxes[j].x2 - boxes[j].x1,
-                       boxes[j].y2 - boxes[j].y1, temp_stride);
-
-                /* For large pixmap, we don't support pbo currently. */
-                assert(pbo == 0);
-                if (_glamor_download_sub_pixmap_to_cpu
-                    (pixmap, format, type, no_alpha, revert, swap_rb,
-                     boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1,
-                     boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits, pbo,
-                     access) == FALSE) {
-                    RegionUninit(&region);
-                    free(sub_bits);
-                    assert(0);
-                    return NULL;
-                }
-                if (boxes[j].x1 != x || temp_stride != stride)
-                    glamor_get_bits(bits, stride, temp_bits, temp_stride,
-                                    pixmap->drawable.bitsPerPixel,
-                                    boxes[j].x1 - x, boxes[j].y1 - y,
-                                    boxes[j].x2 - boxes[j].x1,
-                                    boxes[j].y2 - boxes[j].y1);
-            }
-
-            RegionDestroy(clipped_regions[i].region);
-        }
-        free(sub_bits);
-        free(clipped_regions);
-        RegionUninit(&region);
-        return bits;
-    }
-    else
-        return _glamor_download_sub_pixmap_to_cpu(pixmap, format, type,
-                                                  no_alpha, revert, swap_rb, x,
-                                                  y, w, h, stride, bits, pbo,
-                                                  access);
-}
-
-/**
- * Move a pixmap to CPU memory.
- * The input data is the pixmap's fbo.
- * The output data is at pixmap->devPrivate.ptr. We always use pbo
- * to read the fbo and then map it to va. If possible, we will use
- * it directly as devPrivate.ptr.
- * If successfully download a fbo to cpu then return TRUE.
- * Otherwise return FALSE.
- **/
-Bool
-glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
-{
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    unsigned int stride;
-    void *data = NULL, *dst;
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(pixmap->drawable.pScreen);
-    int pbo = 0;
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return TRUE;
-
-    glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DOWNLOAD,
-                        "Downloading pixmap %p  %dx%d depth%d\n",
-                        pixmap,
-                        pixmap->drawable.width,
-                        pixmap->drawable.height, pixmap->drawable.depth);
-
-    stride = pixmap->devKind;
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
-        || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
-        data = malloc(stride * pixmap->drawable.height);
-    }
-    else {
-        glamor_make_current(glamor_priv);
-        if (pixmap_priv->base.fbo->pbo == 0)
-            glGenBuffers(1, &pixmap_priv->base.fbo->pbo);
-        pbo = pixmap_priv->base.fbo->pbo;
-    }
-
-    if (pixmap_priv->type == GLAMOR_TEXTURE_DRM) {
-        stride = PixmapBytePad(pixmap->drawable.width, pixmap->drawable.depth);
-        pixmap_priv->base.drm_stride = pixmap->devKind;
-        pixmap->devKind = stride;
-    }
-
-    dst = glamor_download_sub_pixmap_to_cpu(pixmap, 0, 0,
-                                            pixmap->drawable.width,
-                                            pixmap->drawable.height,
-                                            pixmap->devKind, data, pbo, access);
-
-    if (!dst) {
-        if (data)
-            free(data);
-        return FALSE;
-    }
-
-    if (pbo != 0)
-        pixmap_priv->base.fbo->pbo_valid = 1;
-
-    pixmap_priv->base.gl_fbo = GLAMOR_FBO_DOWNLOADED;
-
-    pixmap->devPrivate.ptr = dst;
-
-    return TRUE;
-}
-
 /* fixup a fbo to the exact size as the pixmap. */
 /* XXX LARGE pixmap? */
 Bool
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 24f8674..17406ab 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -789,21 +789,6 @@ void
 glamor_put_vbo_space(ScreenPtr screen);
 
 /**
- * Download a pixmap's texture to cpu memory. If success,
- * One copy of current pixmap's texture will be put into
- * the pixmap->devPrivate.ptr. Will use pbo to map to
- * the pointer if possible.
- * The pixmap must be a gl texture pixmap. gl_fbo must be GLAMOR_FBO_NORMAL and
- * gl_tex must be 1. Used by glamor_prepare_access.
- *
- */
-Bool glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access);
-
-void *glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w,
-                                        int h, int stride, void *bits, int pbo,
-                                        glamor_access_t access);
-
-/**
  * Restore a pixmap's data which is downloaded by
  * glamor_download_pixmap_to_cpu to its original
  * gl texture. Used by glamor_finish_access.
commit b6181007de357da58125e022992f165b10eda65d
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 16 07:04:01 2014 +0100

    glamor: Drop dead get/pub sub pixmap functions.
    
    These were replaced by the new glamor_prepare.c code.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 8dbeb22..00e3827 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -1512,132 +1512,3 @@ glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv)
 
     return ret;
 }
-
-/*
- * We may use this function to reduce a large pixmap to a small sub
- * pixmap. Two scenarios currently:
- * 1. When fallback a large textured pixmap to CPU but we do need to
- * do rendering within a small sub region, then we can just get a
- * sub region.
- *
- * 2. When uploading a large pixmap to texture but we only need to
- * use part of the source/mask picture. As glTexImage2D will be more
- * efficient to upload a contingent region rather than a sub block
- * in a large buffer. We use this function to gather the sub region
- * to a contingent sub pixmap.
- *
- * The sub-pixmap must have the same format as the source pixmap.
- *
- * */
-PixmapPtr
-glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y, int w, int h,
-                      glamor_access_t access)
-{
-    glamor_screen_private *glamor_priv;
-    PixmapPtr sub_pixmap;
-    glamor_pixmap_private *sub_pixmap_priv, *pixmap_priv;
-    void *data;
-    int pbo;
-    int flag;
-
-    if (x < 0 || y < 0)
-        return NULL;
-    w = (x + w) > pixmap->drawable.width ? (pixmap->drawable.width - x) : w;
-    h = (y + h) > pixmap->drawable.height ? (pixmap->drawable.height - y) : h;
-
-    glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return NULL;
-    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 ||
-        pixmap_priv->type == GLAMOR_TEXTURE_LARGE)
-        flag = GLAMOR_CREATE_PIXMAP_CPU;
-    else
-        flag = GLAMOR_CREATE_PIXMAP_MAP;
-
-    sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
-                                      pixmap->drawable.depth, flag);
-
-    if (sub_pixmap == NULL)
-        return NULL;
-
-    sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
-    pbo =
-        sub_pixmap_priv ? (sub_pixmap_priv->base.fbo ? sub_pixmap_priv->base.
-                           fbo->pbo : 0) : 0;
-
-    if (pixmap_priv->base.is_picture) {
-        sub_pixmap_priv->base.picture = pixmap_priv->base.picture;
-        sub_pixmap_priv->base.is_picture = pixmap_priv->base.is_picture;
-    }
-
-    if (pbo)
-        data = NULL;
-    else
-        data = sub_pixmap->devPrivate.ptr;
-
-    data =
-        glamor_download_sub_pixmap_to_cpu(pixmap, x, y, w, h,
-                                          sub_pixmap->devKind, data, pbo,
-                                          access);
-    if (data == NULL) {
-        fbDestroyPixmap(sub_pixmap);
-        return NULL;
-    }
-    if (pbo) {
-        assert(sub_pixmap->devPrivate.ptr == NULL);
-        sub_pixmap->devPrivate.ptr = data;
-        sub_pixmap_priv->base.fbo->pbo_valid = 1;
-    }
-#if 0
-    struct pixman_box16 box;
-    PixmapPtr new_sub_pixmap;
-    int dx, dy;
-
-    box.x1 = 0;
-    box.y1 = 0;
-    box.x2 = w;
-    box.y2 = h;
-
-    dx = x;
-    dy = y;
-
-    new_sub_pixmap = glamor_create_pixmap(pixmap->drawable.pScreen, w, h,
-                                          pixmap->drawable.depth,
-                                          GLAMOR_CREATE_PIXMAP_CPU);
-    glamor_copy_n_to_n(&pixmap->drawable, &new_sub_pixmap->drawable, NULL, &box,
-                       1, dx, dy, 0, 0, 0, NULL);
-    glamor_compare_pixmaps(new_sub_pixmap, sub_pixmap, 0, 0, w, h, 1, 1);
-#endif
-
-    return sub_pixmap;
-}
-
-void
-glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
-                      int w, int h, glamor_access_t access)
-{
-    void *bits;
-    int pbo;
-    glamor_pixmap_private *sub_pixmap_priv;
-
-    if (access != GLAMOR_ACCESS_RO) {
-        sub_pixmap_priv = glamor_get_pixmap_private(sub_pixmap);
-        if (sub_pixmap_priv->base.fbo && sub_pixmap_priv->base.fbo->pbo_valid) {
-            bits = NULL;
-            pbo = sub_pixmap_priv->base.fbo->pbo;
-        }
-        else {
-            bits = sub_pixmap->devPrivate.ptr;
-            pbo = 0;
-        }
-
-        assert(x >= 0 && y >= 0);
-        w = (w > sub_pixmap->drawable.width) ? sub_pixmap->drawable.width : w;
-        h = (h > sub_pixmap->drawable.height) ? sub_pixmap->drawable.height : h;
-        glamor_upload_sub_pixmap_to_texture(pixmap, x, y, w, h,
-                                            sub_pixmap->devKind, bits, pbo);
-    }
-    glamor_destroy_pixmap(sub_pixmap);
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 144cbfd..24f8674 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -833,11 +833,6 @@ Bool glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
                                          int h, int stride, void *bits,
                                          int pbo);
 
-PixmapPtr glamor_get_sub_pixmap(PixmapPtr pixmap, int x, int y,
-                                int w, int h, glamor_access_t access);
-void glamor_put_sub_pixmap(PixmapPtr sub_pixmap, PixmapPtr pixmap, int x, int y,
-                           int w, int h, glamor_access_t access);
-
 glamor_pixmap_clipped_regions *
 glamor_compute_clipped_regions(glamor_pixmap_private *priv,
                                RegionPtr region, int *clipped_nbox,
commit e310387f443b6333edf02c8980daa303505382b4
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Jan 12 10:19:10 2014 -0800

    glamor: Remove always-true yInverted flag.
    
    All users of glamor had the same value set, and it complicated things
    for no reason.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 9fb9c67..5e6003d 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -328,11 +328,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         return FALSE;
 
     glamor_priv->flags = flags;
-    if (flags & GLAMOR_INVERTED_Y_AXIS) {
-        glamor_priv->yInverted = TRUE;
-    }
-    else
-        glamor_priv->yInverted = FALSE;
 
     if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
         LogMessage(X_WARNING,
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 2cdb1d4..405dbe8 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -63,7 +63,7 @@ typedef enum glamor_pixmap_type {
 } glamor_pixmap_type_t;
 
 #define GLAMOR_EGL_EXTERNAL_BUFFER 3
-#define GLAMOR_INVERTED_Y_AXIS  	1
+#define GLAMOR_INVERTED_Y_AXIS         1 /* compat stub */
 #define GLAMOR_USE_SCREEN		(1 << 1)
 #define GLAMOR_USE_PICTURE_SCREEN 	(1 << 2)
 #define GLAMOR_USE_EGL_SCREEN		(1 << 3)
@@ -79,12 +79,6 @@ typedef enum glamor_pixmap_type {
  * @screen: Current screen pointer.
  * @flags:  Please refer the flags description above.
  *
- * 	@GLAMOR_INVERTED_Y_AXIS:
- * 	set 1 means the GL env's origin (0,0) is at top-left.
- * 	EGL/DRM platform is an example need to set this bit.
- * 	glx platform's origin is at bottom-left thus need to
- * 	clear this bit.
- *
  * 	@GLAMOR_USE_SCREEN:
  *	If running in an pre-existing X environment, and the
  * 	gl context is GLX, then you should set this bit and
diff --git a/glamor/glamor_gradient.c b/glamor/glamor_gradient.c
index 28d6691..4ded89d 100644
--- a/glamor/glamor_gradient.c
+++ b/glamor/glamor_gradient.c
@@ -699,7 +699,7 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
                                                     width),
                                            (INT16) (dst_picture->pDrawable->
                                                     height),
-                                           glamor_priv->yInverted, vertices);
+                                           vertices);
 
     if (tex_normalize) {
         glamor_set_normalize_tcoords_tri_stripe(*xscale, *yscale,
@@ -710,17 +710,14 @@ _glamor_gradient_set_pixmap_destination(ScreenPtr screen,
                                                 (INT16) (dst_picture->
                                                          pDrawable->height +
                                                          y_source),
-                                                glamor_priv->yInverted,
                                                 tex_vertices);
     }
     else {
-        glamor_set_tcoords_tri_strip((INT16) (dst_picture->pDrawable->width),
-                                     (INT16) (dst_picture->pDrawable->height),
-                                     x_source, y_source,
+        glamor_set_tcoords_tri_strip(x_source, y_source,
                                      (INT16) (dst_picture->pDrawable->width) +
                                      x_source,
                                      (INT16) (dst_picture->pDrawable->height) +
-                                     y_source, glamor_priv->yInverted,
+                                     y_source,
                                      tex_vertices);
     }
 
@@ -1084,13 +1081,11 @@ glamor_generate_radial_gradient_picture(ScreenPtr screen,
     r2 = (float) pixman_fixed_to_double(src_picture->pSourcePict->radial.c2.
                                         radius);
 
-    glamor_set_circle_centre(width, height, c1x, c1y, glamor_priv->yInverted,
-                             cxy);
+    glamor_set_circle_centre(width, height, c1x, c1y, cxy);
     glUniform2fv(c1_uniform_location, 1, cxy);
     glUniform1f(r1_uniform_location, r1);
 
-    glamor_set_circle_centre(width, height, c2x, c2y, glamor_priv->yInverted,
-                             cxy);
+    glamor_set_circle_centre(width, height, c2x, c2y, cxy);
     glUniform2fv(c2_uniform_location, 1, cxy);
     glUniform1f(r2_uniform_location, r2);
 
@@ -1322,7 +1317,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
                                                    linear.p1.x),
                             pixman_fixed_to_double(src_picture->pSourcePict->
                                                    linear.p1.y),
-                            glamor_priv->yInverted, pt1);
+                            pt1);
     DEBUGF("pt1:(%f, %f) ---> (%f %f)\n",
            pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.x),
            pixman_fixed_to_double(src_picture->pSourcePict->linear.p1.y),
@@ -1333,7 +1328,7 @@ glamor_generate_linear_gradient_picture(ScreenPtr screen,
                                                    linear.p2.x),
                             pixman_fixed_to_double(src_picture->pSourcePict->
                                                    linear.p2.y),
-                            glamor_priv->yInverted, pt2);
+                            pt2);
     DEBUGF("pt2:(%f, %f) ---> (%f %f)\n",
            pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.x),
            pixman_fixed_to_double(src_picture->pSourcePict->linear.p2.y),
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 54b414b..8dbeb22 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -746,11 +746,6 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
         glamor_get_screen_private(pixmap->drawable.pScreen);
     static float vertices[8];
 
-    static float texcoords[8] = { 0, 1,
-        1, 1,
-        1, 0,
-        0, 0
-    };
     static float texcoords_inv[8] = { 0, 0,
         1, 0,
         1, 1,
@@ -759,11 +754,8 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
     float *ptexcoords;
     float dst_xscale, dst_yscale;
     GLuint tex = 0;
-    int need_flip;
     int need_free_bits = 0;
 
-    need_flip = !glamor_priv->yInverted;
-
     if (bits == NULL)
         goto ready_to_upload;
 
@@ -797,7 +789,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
     /* Try fast path firstly, upload the pixmap to the texture attached
      * to the fbo directly. */
     if (no_alpha == 0
-        && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING && !need_flip
+        && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING
 #ifdef WALKAROUND_LARGE_TEXTURE_MAP
         && pixmap_priv->type != GLAMOR_TEXTURE_LARGE
 #endif
@@ -817,17 +809,14 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
         return TRUE;
     }
 
-    if (need_flip)
-        ptexcoords = texcoords;
-    else
-        ptexcoords = texcoords_inv;
+    ptexcoords = texcoords_inv;
 
     pixmap_priv_get_dest_scale(pixmap_priv, &dst_xscale, &dst_yscale);
     glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
                                  dst_yscale,
                                  x, y,
                                  x + w, y + h,
-                                 glamor_priv->yInverted, vertices);
+                                 vertices);
     /* Slow path, we need to flip y or wire alpha to 1. */
     glamor_make_current(glamor_priv);
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
@@ -864,10 +853,7 @@ _glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
 /*
  * Prepare to upload a pixmap to texture memory.
  * no_alpha equals 1 means the format needs to wire alpha to 1.
- * Two condtion need to setup a fbo for a pixmap
- * 1. !yInverted, we need to do flip if we are not yInverted.
- * 2. no_alpha != 0, we need to wire the alpha.
- * */
+ */
 static int
 glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
                              int revert, int swap_rb)
@@ -895,8 +881,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
         return 0;
 
     if (!(no_alpha || (revert == REVERT_NORMAL)
-          || (swap_rb != SWAP_NONE_UPLOADING)
-          || !glamor_priv->yInverted)) {
+          || (swap_rb != SWAP_NONE_UPLOADING))) {
         /* We don't need a fbo, a simple texture uploading should work. */
 
         flag = GLAMOR_CREATE_FBO_NO_FBO;
@@ -1141,7 +1126,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
 
     glamor_set_normalize_vcoords((struct glamor_pixmap_private *) NULL,
                                  temp_xscale, temp_yscale, 0, 0, w, h,
-                                 glamor_priv->yInverted, vertices);
+                                 vertices);
 
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
                           2 * sizeof(float), vertices);
@@ -1152,7 +1137,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, int x, int y, int w, int h,
                                  source_yscale,
                                  x, y,
                                  x + w, y + h,
-                                 glamor_priv->yInverted, texcoords);
+                                 texcoords);
 
     glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
                           2 * sizeof(float), texcoords);
@@ -1190,7 +1175,7 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
 {
     glamor_pixmap_private *pixmap_priv;
     GLenum gl_access = 0, gl_usage = 0;
-    void *data, *read;
+    void *data;
     glamor_screen_private *glamor_priv =
         glamor_get_screen_private(pixmap->drawable.pScreen);
     glamor_pixmap_fbo *temp_fbo = NULL;
@@ -1252,46 +1237,17 @@ _glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, GLenum format,
 
     glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
-    if (glamor_priv->has_pack_invert || glamor_priv->yInverted) {
-
-        if (!glamor_priv->yInverted) {
-            assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
-            glPixelStorei(GL_PACK_INVERT_MESA, 1);
-        }
-
-        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) {
-            assert(pbo > 0);
-            glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
-            glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, gl_usage);
-        }
-
-        glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
-
-        if (!glamor_priv->yInverted) {
-            assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
-            glPixelStorei(GL_PACK_INVERT_MESA, 0);
-        }
-        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) {
-            bits = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
-            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-        }
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && data == NULL) {
+        assert(pbo > 0);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
+        glBufferData(GL_PIXEL_PACK_BUFFER, stride * h, NULL, gl_usage);
     }
-    else {
-        unsigned int temp_pbo;
-        int yy;
 
-        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);
-        glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, 0);
-        read = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
-        for (yy = 0; yy < pixmap->drawable.height; yy++)
-            memcpy((char *) data + yy * stride,
-                   (char *) read + (h - yy - 1) * stride, stride);
-        glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+    glReadPixels(x + fbo_x_off, y + fbo_y_off, w, h, format, type, data);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP && bits == NULL) {
+        bits = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-        glDeleteBuffers(1, &temp_pbo);
     }
 
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -1461,7 +1417,6 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
     stride = pixmap->devKind;
 
     if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
-        || (!glamor_priv->has_pack_invert && !glamor_priv->yInverted)
         || pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
         data = malloc(stride * pixmap->drawable.height);
     }
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 670cdd3..144cbfd 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -200,7 +200,6 @@ struct glamor_saved_procs {
 #define RENDER_IDEL_MAX 32
 
 typedef struct glamor_screen_private {
-    Bool yInverted;
     unsigned int tick;
     enum glamor_gl_flavor gl_flavor;
     int glsl_version;
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 6da38da..add376f 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -793,30 +793,29 @@ glamor_set_normalize_tcoords_generic(glamor_pixmap_private *priv,
                                      float *matrix,
                                      float xscale, float yscale,
                                      int x1, int y1, int x2, int y2,
-                                     int yInverted, float *texcoords,
+                                     float *texcoords,
                                      int stride)
 {
     if (!matrix && repeat_type == RepeatNone)
         glamor_set_normalize_tcoords_ext(priv, xscale, yscale,
                                          x1, y1,
-                                         x2, y2, yInverted, texcoords, stride);
+                                         x2, y2, texcoords, stride);
     else if (matrix && repeat_type == RepeatNone)
         glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale,
                                                      yscale, x1, y1,
                                                      x2, y2,
-                                                     yInverted,
                                                      texcoords, stride);
     else if (!matrix && repeat_type != RepeatNone)
         glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type,
                                                 xscale, yscale,
                                                 x1, y1,
                                                 x2, y2,
-                                                yInverted, texcoords, stride);
+                                                texcoords, stride);
     else if (matrix && repeat_type != RepeatNone)
         glamor_set_repeat_transformed_normalize_tcoords_ext(priv, repeat_type,
                                                             matrix, xscale,
                                                             yscale, x1, y1, x2,
-                                                            y2, yInverted,
+                                                            y2,
                                                             texcoords, stride);
 }
 
@@ -1266,7 +1265,7 @@ glamor_composite_with_shader(CARD8 op,
             glamor_set_normalize_vcoords_ext(dest_pixmap_priv, dst_xscale,
                                              dst_yscale, x_dest, y_dest,
                                              x_dest + width, y_dest + height,
-                                             glamor_priv->yInverted, vertices,
+                                             vertices,
                                              vb_stride);
             vertices += 2;
             if (key.source != SHADER_SOURCE_SOLID) {
@@ -1276,7 +1275,6 @@ glamor_composite_with_shader(CARD8 op,
                                                      src_yscale, x_source,
                                                      y_source, x_source + width,
                                                      y_source + height,
-                                                     glamor_priv->yInverted,
                                                      vertices, vb_stride);
                 vertices += 2;
             }
@@ -1288,7 +1286,6 @@ glamor_composite_with_shader(CARD8 op,
                                                      mask_yscale, x_mask,
                                                      y_mask, x_mask + width,
                                                      y_mask + height,
-                                                     glamor_priv->yInverted,
                                                      vertices, vb_stride);
                 vertices += 2;
             }
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index cdf5fa2..d61d11f 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -908,7 +908,6 @@ _glamor_trapezoids_with_shader(CARD8 op,
                         clipped_vtx_tmp[5] = clipped_vtx[(i + 2) * 2 + 1];
                         glamor_set_normalize_tri_vcoords(dst_xscale, dst_yscale,
                                                          clipped_vtx_tmp,
-                                                         glamor_priv->yInverted,
                                                          vertices);
                         DEBUGF("vertices of triangle: (%f X %f), (%f X %f), "
                                "(%f X %f)\n", vertices[0], vertices[1],
@@ -920,14 +919,12 @@ _glamor_trapezoids_with_shader(CARD8 op,
                                 glamor_set_transformed_normalize_tri_tcoords
                                     (source_pixmap_priv, src_matrix, src_xscale,
                                      src_yscale, clipped_vtx_tmp,
-                                     glamor_priv->yInverted, source_texcoords);
+                                     source_texcoords);
                             }
                             else {
                                 glamor_set_normalize_tri_tcoords(src_xscale,
                                                                  src_yscale,
                                                                  clipped_vtx_tmp,
-                                                                 glamor_priv->
-                                                                 yInverted,
                                                                  source_texcoords);
                             }
 
@@ -1439,11 +1436,9 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
             miTrapezoidBounds(1, ptrap, &one_trap_bound);
 
             vertices += 2;
-            glamor_set_tcoords_ext((pixmap_priv->base.pixmap->drawable.width),
-                                   (pixmap_priv->base.pixmap->drawable.height),
-                                   (one_trap_bound.x1), (one_trap_bound.y1),
+            glamor_set_tcoords_ext((one_trap_bound.x1), (one_trap_bound.y1),
                                    (one_trap_bound.x2), (one_trap_bound.y2),
-                                   glamor_priv->yInverted, vertices, stride);
+                                   vertices, stride);
             DEBUGF("tex_vertices --> leftup : %f X %f, rightup: %f X %f,"
                    "rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0],
                    vertices[1], vertices[1 * stride], vertices[1 * stride + 1],
@@ -1463,8 +1458,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
                                              one_trap_bound.y1,
                                              one_trap_bound.x2,
                                              one_trap_bound.y2,
-                                             glamor_priv->yInverted, vertices,
-                                             stride);
+                                             vertices, stride);
             DEBUGF("vertices --> leftup : %f X %f, rightup: %f X %f,"
                    "rightbottom: %f X %f, leftbottom : %f X %f\n", vertices[0],
                    vertices[1], vertices[1 * stride], vertices[1 * stride + 1],
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index 5a568f1..c15d17c 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -313,21 +313,17 @@
   } while(0)
 
 #define _glamor_set_normalize_tpoint(xscale, yscale, _tx_, _ty_,	\
-				     texcoord, yInverted)		\
+				     texcoord)                          \
   do {									\
 	(texcoord)[0] = t_from_x_coord_x(xscale, _tx_);			\
-	if (_X_LIKELY(yInverted))					\
-		(texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);\
-	else								\
-		(texcoord)[1] = t_from_x_coord_y(yscale, _ty_);		\
+        (texcoord)[1] = t_from_x_coord_y_inverted(yscale, _ty_);        \
         DEBUGF("normalized point tx %f ty %f \n", (texcoord)[0],	\
 		(texcoord)[1]);						\
   } while(0)
 
 #define glamor_set_transformed_point(priv, matrix, xscale,		\
 				     yscale, texcoord,			\
-                                     x, y, 				\
-				     yInverted)				\
+                                     x, y)				\
   do {									\
     float tx, ty;							\
     int fbo_x_off, fbo_y_off;						\
@@ -339,10 +335,7 @@
     tx += fbo_x_off;							\
     ty += fbo_y_off;							\
     (texcoord)[0] = t_from_x_coord_x(xscale, tx);			\
-    if (_X_LIKELY(yInverted))						\
-      (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty);		\
-    else								\
-      (texcoord)[1] = t_from_x_coord_y(yscale, ty);			\
+    (texcoord)[1] = t_from_x_coord_y_inverted(yscale, ty);		\
     DEBUGF("normalized tx %f ty %f \n", (texcoord)[0], (texcoord)[1]);	\
   } while(0)
 
@@ -351,18 +344,14 @@
 						     xscale,		\
 						     yscale,		\
 						     vtx,		\
-						     yInverted,		\
 						     texcoords)		\
     do {								\
 	glamor_set_transformed_point(priv, matrix, xscale, yscale,	\
-				     texcoords, (vtx)[0], (vtx)[1],	\
-				     yInverted);			\
+				     texcoords, (vtx)[0], (vtx)[1]);    \
 	glamor_set_transformed_point(priv, matrix, xscale, yscale,	\
-				     texcoords+2, (vtx)[2], (vtx)[3],	\
-				     yInverted);			\
+				     texcoords+2, (vtx)[2], (vtx)[3]);  \
 	glamor_set_transformed_point(priv, matrix, xscale, yscale,	\
-				     texcoords+4, (vtx)[4], (vtx)[5],	\
-				     yInverted);			\
+				     texcoords+4, (vtx)[4], (vtx)[5]);  \
     } while (0)
 
 #define glamor_set_transformed_normalize_tcoords_ext( priv,		\
@@ -370,21 +359,17 @@
 						  xscale,		\
 						  yscale,		\
                                                   tx1, ty1, tx2, ty2,   \
-                                                  yInverted, texcoords,	\
+                                                  texcoords,		\
 						  stride)		\
   do {									\
     glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
-				 texcoords, tx1, ty1,			\
-				 yInverted);				\
+				 texcoords, tx1, ty1);                  \
     glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
-				 texcoords + 1 * stride, tx2, ty1,	\
-				 yInverted);				\
+				 texcoords + 1 * stride, tx2, ty1);     \
     glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
-				 texcoords + 2 * stride, tx2, ty2,	\
-				 yInverted);				\
+				 texcoords + 2 * stride, tx2, ty2);     \
     glamor_set_transformed_point(priv, matrix, xscale, yscale,		\
-				 texcoords + 3 * stride, tx1, ty2,	\
-				 yInverted);				\
+				 texcoords + 3 * stride, tx1, ty2);     \
   } while (0)
 
 #define glamor_set_transformed_normalize_tcoords( priv,			\
@@ -392,35 +377,31 @@
 						  xscale,		\
 						  yscale,		\
                                                   tx1, ty1, tx2, ty2,   \
-                                                  yInverted, texcoords)	\
+                                                  texcoords)            \
   do {									\
 	glamor_set_transformed_normalize_tcoords_ext( priv,		\
 						  matrix,		\
 						  xscale,		\
 						  yscale,		\
                                                   tx1, ty1, tx2, ty2,   \
-                                                  yInverted, texcoords,	\
+                                                  texcoords,		\
 						  2);			\
   } while (0)
 
 #define glamor_set_normalize_tri_tcoords(xscale,		\
 					 yscale,		\
 					 vtx,			\
-					 yInverted,		\
 					 texcoords)		\
     do {							\
 	_glamor_set_normalize_tpoint(xscale, yscale,		\
 				(vtx)[0], (vtx)[1],		\
-				texcoords,			\
-				yInverted);			\
+				texcoords);			\
 	_glamor_set_normalize_tpoint(xscale, yscale,		\
 				(vtx)[2], (vtx)[3],		\
-				texcoords+2,			\
-				yInverted);			\
+				texcoords+2);			\
 	_glamor_set_normalize_tpoint(xscale, yscale,		\
 				(vtx)[4], (vtx)[5],		\
-				texcoords+4,			\
-				yInverted);			\
+				texcoords+4);			\
     } while (0)
 
 #define glamor_set_repeat_transformed_normalize_tcoords_ext( priv,	\
@@ -430,14 +411,13 @@
 							 yscale,	\
 							 _x1_, _y1_,	\
 							 _x2_, _y2_,   	\
-							 yInverted,	\
 							 texcoords,	\
 							 stride)	\
   do {									\
     if (_X_LIKELY(priv->type != GLAMOR_TEXTURE_LARGE)) {		\
 	glamor_set_transformed_normalize_tcoords_ext(priv, matrix, xscale,	\
 						 yscale, _x1_, _y1_,	\
-						 _x2_, _y2_, yInverted,	\
+						 _x2_, _y2_,	\
 						 texcoords, stride);	\
     } else {								\
     float tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;			\
@@ -464,13 +444,13 @@
     DEBUGF("repeat transformed %f %f %f %f %f %f %f %f\n", ttx1, tty1, 	\
 	    ttx2, tty2,	ttx3, tty3, ttx4, tty4);			\
     _glamor_set_normalize_tpoint(xscale, yscale, ttx1, tty1,		\
-				 texcoords, yInverted);			\
+				 texcoords);			\
     _glamor_set_normalize_tpoint(xscale, yscale, ttx2, tty2,		\
-				 texcoords + 1 * stride, yInverted);	\
+				 texcoords + 1 * stride);	\
     _glamor_set_normalize_tpoint(xscale, yscale, ttx3, tty3,		\
-				 texcoords + 2 * stride, yInverted);	\
+				 texcoords + 2 * stride);	\
     _glamor_set_normalize_tpoint(xscale, yscale, ttx4, tty4,		\
-				 texcoords + 3 * stride, yInverted);	\
+				 texcoords + 3 * stride);	\
    }									\
   } while (0)
 
@@ -481,7 +461,6 @@
 							 yscale,	\
 							 _x1_, _y1_,	\
 							 _x2_, _y2_,   	\
-							 yInverted,	\
 							 texcoords)	\
   do {									\
 	glamor_set_repeat_transformed_normalize_tcoords_ext( priv,	\
@@ -491,14 +470,13 @@
 							 yscale,	\
 							 _x1_, _y1_,	\
 							 _x2_, _y2_,   	\
-							 yInverted,	\
 							 texcoords,	\
 							 2);	\
   } while (0)
 
 #define _glamor_set_normalize_tcoords(xscale, yscale, tx1,		\
 				      ty1, tx2, ty2,			\
-				      yInverted, vertices, stride)	\
+				      vertices, stride)                 \
   do {									\
     /* vertices may be write-only, so we use following			\
      * temporary variable. */ 						\
@@ -507,21 +485,15 @@
     (vertices)[1 * stride] = _t2_ = t_from_x_coord_x(xscale, tx2);	\
     (vertices)[2 * stride] = _t2_;					\
     (vertices)[3 * stride] = _t0_;					\
-    if (_X_LIKELY(yInverted)) {						\
-      (vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1);	\
-      (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2);\
-    }									\
-    else {								\
-      (vertices)[1] = _t1_ = t_from_x_coord_y(yscale, ty1);		\
-      (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y(yscale, ty2);\
-    }									\
+    (vertices)[1] = _t1_ = t_from_x_coord_y_inverted(yscale, ty1);	\
+    (vertices)[2 * stride + 1] = _t5_ = t_from_x_coord_y_inverted(yscale, ty2); \
     (vertices)[1 * stride + 1] = _t1_;					\
     (vertices)[3 * stride + 1] = _t5_;					\
   } while(0)
 
 #define glamor_set_normalize_tcoords_ext(priv, xscale, yscale,		\
 				     x1, y1, x2, y2,			\
-                                     yInverted, vertices, stride)	\
+                                     vertices, stride)	\
   do {									\
      if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) {		\
 	float tx1, tx2, ty1, ty2;					\
@@ -532,26 +504,26 @@
 	ty1 = y1 + fbo_y_off;						\
 	ty2 = y2 + fbo_y_off;						\
 	_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1,		\
-				   tx2, ty2, yInverted, vertices,	\
+                                      tx2, ty2, vertices,               \
 				   stride);				\
      } else								\
 	_glamor_set_normalize_tcoords(xscale, yscale, x1, y1,		\
-				   x2, y2, yInverted, vertices, stride);\
+                                      x2, y2, vertices, stride);        \
  } while(0)
 
 #define glamor_set_normalize_tcoords(priv, xscale, yscale,		\
 				     x1, y1, x2, y2,			\
-                                     yInverted, vertices)		\
+                                     vertices)		\
   do {									\
 	glamor_set_normalize_tcoords_ext(priv, xscale, yscale,		\
 				     x1, y1, x2, y2,			\
-                                     yInverted, vertices, 2);		\
+                                     vertices, 2);			\
  } while(0)
 
 #define glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type,	\
 					    xscale, yscale,		\
 					    _x1_, _y1_, _x2_, _y2_,	\
-	                                    yInverted, vertices, stride)\
+	                                    vertices, stride)		\
   do {									\
      if (_X_UNLIKELY(priv->type == GLAMOR_TEXTURE_LARGE)) {		\
 	float tx1, tx2, ty1, ty2;					\
@@ -566,130 +538,99 @@
 				 _x1_, _y1_, _x2_, _y2_);		\
 	}								\
 	_glamor_set_normalize_tcoords(xscale, yscale, tx1, ty1,		\
-				   tx2, ty2, yInverted, vertices,	\
+                                      tx2, ty2, vertices,               \
 				   stride);				\
      } else								\
 	_glamor_set_normalize_tcoords(xscale, yscale, _x1_, _y1_,	\
-				   _x2_, _y2_, yInverted, vertices,	\
+                                      _x2_, _y2_, vertices,             \
 				   stride);				\
  } while(0)
 
 #define glamor_set_repeat_normalize_tcoords(priv, repeat_type,		\
 					    xscale, yscale,		\
 					    _x1_, _y1_, _x2_, _y2_,	\
-	                                    yInverted, vertices)	\
+	                                    vertices)                   \
   do {									\
 	glamor_set_repeat_normalize_tcoords_ext(priv, repeat_type,	\
 					    xscale, yscale,		\
 					    _x1_, _y1_, _x2_, _y2_,	\
-	                                    yInverted, vertices, 2);	\
+	                                    vertices, 2);		\
  } while(0)
 
 #define glamor_set_normalize_tcoords_tri_stripe(xscale, yscale,		\
 						x1, y1, x2, y2,		\
-						yInverted, vertices)	\
+						vertices)               \
     do {								\
 	(vertices)[0] = t_from_x_coord_x(xscale, x1);			\
 	(vertices)[2] = t_from_x_coord_x(xscale, x2);			\
 	(vertices)[6] = (vertices)[2];					\
 	(vertices)[4] = (vertices)[0];					\
-	if (_X_LIKELY(yInverted)) {					\
-	    (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1);	\
-	    (vertices)[7] = t_from_x_coord_y_inverted(yscale, y2);	\
-	}								\
-	else {								\
-	    (vertices)[1] = t_from_x_coord_y(yscale, y1);		\
-	    (vertices)[7] = t_from_x_coord_y(yscale, y2);		\
-	}								\
+        (vertices)[1] = t_from_x_coord_y_inverted(yscale, y1);          \
+        (vertices)[7] = t_from_x_coord_y_inverted(yscale, y2);          \
 	(vertices)[3] = (vertices)[1];					\
 	(vertices)[5] = (vertices)[7];					\
     } while(0)
 
-#define glamor_set_tcoords(width, height, x1, y1, x2, y2,	\
-			   yInverted, vertices)			\
+#define glamor_set_tcoords(x1, y1, x2, y2, vertices)            \
     do {							\
 	(vertices)[0] = (x1);					\
 	(vertices)[2] = (x2);					\
 	(vertices)[4] = (vertices)[2];				\
 	(vertices)[6] = (vertices)[0];				\
-	if (_X_LIKELY(yInverted)) {				\
-	    (vertices)[1] = (y1);				\
-	    (vertices)[5] = (y2);				\
-	}							\
-	else {							\
-	    (vertices)[1] = height - (y2);			\
-	    (vertices)[5] = height - (y1);			\
-	}							\
+        (vertices)[1] = (y1);                                   \
+        (vertices)[5] = (y2);                                   \
 	(vertices)[3] = (vertices)[1];				\
 	(vertices)[7] = (vertices)[5];				\
     } while(0)
 
-#define glamor_set_tcoords_ext(width, height, x1, y1, x2, y2,	\
-			       yInverted, vertices, stride)	\
+#define glamor_set_tcoords_ext(x1, y1, x2, y2, vertices, stride)        \
     do {							\
 	(vertices)[0] = (x1);					\
 	(vertices)[1*stride] = (x2);				\
 	(vertices)[2*stride] = (vertices)[1*stride];		\
 	(vertices)[3*stride] = (vertices)[0];			\
-	if (_X_LIKELY(yInverted)) {				\
-	    (vertices)[1] = (y1);				\
-	    (vertices)[2*stride + 1] = (y2);			\
-	}							\
-	else {							\
-	    (vertices)[1] = height - (y2);			\
-	    (vertices)[2*stride + 1] = height - (y1);		\
-	}							\
+        (vertices)[1] = (y1);                                   \
+        (vertices)[2*stride + 1] = (y2);			\
 	(vertices)[1*stride + 1] = (vertices)[1];		\
 	(vertices)[3*stride + 1] = (vertices)[2*stride + 1];	\
     } while(0)
 
 #define glamor_set_normalize_one_vcoord(xscale, yscale, x, y,		\
-					yInverted, vertices)		\
+					vertices)                       \
     do {								\
 	(vertices)[0] = v_from_x_coord_x(xscale, x);			\
-	if (_X_LIKELY(yInverted)) {					\
-	    (vertices)[1] = v_from_x_coord_y_inverted(yscale, y);	\
-	} else {							\
-	    (vertices)[1] = v_from_x_coord_y(yscale, y);		\
-	}								\
+        (vertices)[1] = v_from_x_coord_y_inverted(yscale, y);           \
     } while(0)
 
 #define glamor_set_normalize_tri_vcoords(xscale, yscale, vtx,		\
-					 yInverted, vertices)		\
+					 vertices)                      \
     do {								\
 	glamor_set_normalize_one_vcoord(xscale, yscale,			\
 					(vtx)[0], (vtx)[1],		\
-					yInverted, vertices);		\
+					vertices);                      \
 	glamor_set_normalize_one_vcoord(xscale, yscale,			\
 					(vtx)[2], (vtx)[3],		\
-					yInverted, vertices+2);		\
+					vertices+2);                    \
 	glamor_set_normalize_one_vcoord(xscale, yscale,			\
 					(vtx)[4], (vtx)[5],		\
-					yInverted, vertices+4);		\
+					vertices+4);                    \
     } while(0)
 
-#define glamor_set_tcoords_tri_strip(width, height, x1, y1, x2, y2,	\
-				     yInverted, vertices)		\
+#define glamor_set_tcoords_tri_strip(x1, y1, x2, y2, vertices)          \
     do {								\
 	(vertices)[0] = (x1);						\
 	(vertices)[2] = (x2);						\
 	(vertices)[6] = (vertices)[2];					\
 	(vertices)[4] = (vertices)[0];					\
-	if (_X_LIKELY(yInverted)) {	    				\
-	    (vertices)[1] = (y1);					\
-	    (vertices)[7] = (y2);					\
-	}								\
-	else {								\
-	    (vertices)[1] = height - (y2);				\
-	    (vertices)[7] = height - (y1);				\
-	}								\
+        (vertices)[1] = (y1);                                           \
+        (vertices)[7] = (y2);                                           \
 	(vertices)[3] = (vertices)[1];					\
 	(vertices)[5] = (vertices)[7];					\
     } while(0)
 
 #define glamor_set_normalize_vcoords_ext(priv, xscale, yscale,		\
 				     x1, y1, x2, y2,			\
-                                     yInverted, vertices, stride)	\
+                                         vertices, stride)              \
   do {									\
     int fbo_x_off, fbo_y_off;						\
     /* vertices may be write-only, so we use following			\
@@ -701,29 +642,22 @@
 					x2 + fbo_x_off);		\
     (vertices)[2 * stride] = _t2_;					\
     (vertices)[3 * stride] = _t0_;					\
-    if (_X_LIKELY(yInverted)) {						\
-      (vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale,		\
-				y1 + fbo_y_off);			\
-      (vertices)[2 * stride + 1] = _t5_ =				\
-			v_from_x_coord_y_inverted(yscale,		\
-					y2 + fbo_y_off);		\
-    }									\
-    else {								\
-      (vertices)[1] = _t1_ = v_from_x_coord_y(yscale, y1 + fbo_y_off);	\
-      (vertices)[2 * stride + 1] = _t5_ = v_from_x_coord_y(yscale,	\
-					y2 + fbo_y_off);		\
-    }									\
+    (vertices)[1] = _t1_ = v_from_x_coord_y_inverted(yscale,		\
+                                                     y1 + fbo_y_off);   \
+    (vertices)[2 * stride + 1] = _t5_ =                                 \
+        v_from_x_coord_y_inverted(yscale,                               \
+                                  y2 + fbo_y_off);                      \
     (vertices)[1 * stride + 1] = _t1_;					\
     (vertices)[3 * stride + 1] = _t5_;					\
   } while(0)
 
 #define glamor_set_normalize_vcoords(priv, xscale, yscale,		\
 				     x1, y1, x2, y2,			\
-                                     yInverted, vertices)		\
+                                     vertices)				\
   do {									\
 	glamor_set_normalize_vcoords_ext(priv, xscale, yscale,		\
 				     x1, y1, x2, y2,			\
-                                     yInverted, vertices, 2);		\
+                                     vertices, 2);			\
   } while(0)
 
 #define glamor_set_const_ext(params, nparam, vertices, nverts, stride)	\
@@ -738,44 +672,30 @@
 
 #define glamor_set_normalize_vcoords_tri_strip(xscale, yscale,		\
 					       x1, y1, x2, y2,		\
-					       yInverted, vertices)	\
+					       vertices)		\
     do {								\
 	(vertices)[0] = v_from_x_coord_x(xscale, x1);			\
 	(vertices)[2] = v_from_x_coord_x(xscale, x2);			\
 	(vertices)[6] = (vertices)[2];					\
 	(vertices)[4] = (vertices)[0];					\
-	if (_X_LIKELY(yInverted)) {	    				\
-	    (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1);	\
-	    (vertices)[7] = v_from_x_coord_y_inverted(yscale, y2);	\
-	}								\
-	else {								\
-	    (vertices)[1] = v_from_x_coord_y(yscale, y1);		\
-	    (vertices)[7] = v_from_x_coord_y(yscale, y2);		\
-	}								\
+        (vertices)[1] = v_from_x_coord_y_inverted(yscale, y1);          \
+        (vertices)[7] = v_from_x_coord_y_inverted(yscale, y2);          \
 	(vertices)[3] = (vertices)[1];					\
 	(vertices)[5] = (vertices)[7];					\
     } while(0)
 
 #define glamor_set_normalize_pt(xscale, yscale, x, y,		\
-                                yInverted, pt)			\
+                                pt)				\
     do {							\
         (pt)[0] = t_from_x_coord_x(xscale, x);			\
-        if (_X_LIKELY(yInverted)) {				\
-            (pt)[1] = t_from_x_coord_y_inverted(yscale, y);	\
-        } else {						\
-            (pt)[1] = t_from_x_coord_y(yscale, y);		\
-        }							\
+        (pt)[1] = t_from_x_coord_y_inverted(yscale, y);         \
     } while(0)
 
 #define glamor_set_circle_centre(width, height, x, y,	\
-				 yInverted, c)		\
+				 c)		\
     do {						\
         (c)[0] = (float)x;				\
-        if (_X_LIKELY(yInverted)) {	    		\
-            (c)[1] = (float)y;				\
-        } else {					\
-            (c)[1] = (float)height - (float)y;		\
-        }						\
+        (c)[1] = (float)y;				\
     } while(0)
 
 inline static void
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 1e8bdb8..68a06a4 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -360,7 +360,7 @@ glamor_xv_render(glamor_port_private *port_priv)
                                      dsty,
                                      dstx + dstw,
                                      dsty + dsth,
-                                     glamor_priv->yInverted, vertices);
+                                     vertices);
 
         glamor_set_normalize_tcoords(src_pixmap_priv[0],
                                      src_xscale[0],
@@ -369,7 +369,7 @@ glamor_xv_render(glamor_port_private *port_priv)
                                      srcy,
                                      srcx + srcw,
                                      srcy + srch,
-                                     glamor_priv->yInverted, texcoords);
+                                     texcoords);
 
         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     }
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index b156fb9..1c75974 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -1245,8 +1245,7 @@ ephyr_glamor_init(ScreenPtr screen)
 
     glamor_init(screen,
                 GLAMOR_USE_SCREEN |
-                GLAMOR_USE_PICTURE_SCREEN |
-                GLAMOR_INVERTED_Y_AXIS);
+                GLAMOR_USE_PICTURE_SCREEN);
 
     return TRUE;
 }
commit d71ecbb458c15fda608654b78d99683ebeab3c60
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Apr 6 07:22:26 2014 -0700

    glamor: Drop constant arguments to glamor_solid().
    
    After keithp's change to drop the old glamor_fill() code, nothing ever
    changed these values.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index ba7d342..f570d75 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -168,7 +168,7 @@ clear_mask_cache(struct glamor_glyph_mask_cache *maskcache)
     struct glamor_glyph_mask_cache_entry *mce;
 
     glamor_solid(maskcache->pixmap, 0, CACHE_PICTURE_SIZE, CACHE_PICTURE_SIZE,
-                 MASK_CACHE_MAX_SIZE, GXcopy, 0xFFFFFFFF, 0);
+                 MASK_CACHE_MAX_SIZE, 0);
     mce = &maskcache->mcache[0];
     while (cnt--) {
         mce->width = 0;
@@ -1433,7 +1433,7 @@ glamor_glyphs_via_mask(CARD8 op,
             glamor_destroy_pixmap(mask_pixmap);
             return;
         }
-        glamor_solid(mask_pixmap, 0, 0, width, height, GXcopy, 0xFFFFFFFF, 0);
+        glamor_solid(mask_pixmap, 0, 0, width, height, 0);
         component_alpha = NeedsComponent(mask_format->format);
         mask = CreatePicture(0, &mask_pixmap->drawable,
                              mask_format, CPComponentAlpha,
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 535d0ca..670cdd3 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -1025,7 +1025,6 @@ void glamor_composite_rectangles(CARD8 op,
 /* glamor_util.c */
 void
 glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
-             unsigned char alu, unsigned long planemask,
              unsigned long fg_pixel);
 
 void
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 4ad0672..cdf5fa2 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -1393,8 +1393,7 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
 
     /* First, clear all to zero */
     glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width,
-                 pixmap_priv->base.pixmap->drawable.height,
-                 GXclear, 0xFFFFFFFF, 0);
+                 pixmap_priv->base.pixmap->drawable.height, 0);
 
     glamor_make_current(glamor_priv);
 
diff --git a/glamor/glamor_utils.c b/glamor/glamor_utils.c
index 5459d79..f068960 100644
--- a/glamor/glamor_utils.c
+++ b/glamor/glamor_utils.c
@@ -56,21 +56,18 @@ glamor_solid_boxes(PixmapPtr pixmap,
 
 void
 glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
-             unsigned char alu, unsigned long planemask,
              unsigned long fg_pixel)
 {
     DrawablePtr drawable = &pixmap->drawable;
     GCPtr gc;
-    ChangeGCVal vals[3];
+    ChangeGCVal vals[1];
     xRectangle rect;
 
-    vals[0].val = alu;
-    vals[1].val = planemask;
-    vals[2].val = fg_pixel;
+    vals[0].val = fg_pixel;
     gc = GetScratchGC(drawable->depth, drawable->pScreen);
     if (!gc)
         return;
-    ChangeGC(NullClient, gc, GCFunction|GCPlaneMask|GCForeground, vals);
+    ChangeGC(NullClient, gc, GCForeground, vals);
     ValidateGC(drawable, gc);
     rect.x = x;
     rect.y = y;
commit db9bff5c389f96991df8d6c62df1174e62e937d3
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 2 12:09:47 2014 -0700

    glamor: Drop unnecessary glTexParameteri() in upload of texture data.
    
    We're not drawing, and we're not initially setting up the texture for
    later drawing.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
index 4eea902..8914155 100644
--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -72,9 +72,6 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
 
     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);
-
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
 
commit 1140a89d7762540965ff865d154cb0528049066f
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 2 12:12:06 2014 -0700

    glamor: Use MIN/MAX macros to clean up glamor_transfer.c
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
index ad875c9..4eea902 100644
--- a/glamor/glamor_transfer.c
+++ b/glamor/glamor_transfer.c
@@ -90,27 +90,14 @@ glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
         while (nbox--) {
 
             /* compute drawable coordinates */
-            int x1 = boxes->x1 + dx_dst;
-            int x2 = boxes->x2 + dx_dst;
-            int y1 = boxes->y1 + dy_dst;
-            int y2 = boxes->y2 + dy_dst;
+            int x1 = MAX(boxes->x1 + dx_dst, box->x1);
+            int x2 = MIN(boxes->x2 + dx_dst, box->x2);
+            int y1 = MAX(boxes->y1 + dy_dst, box->y1);
+            int y2 = MIN(boxes->y2 + dy_dst, box->y2);
 
             boxes++;
 
-            if (x1 < box->x1)
-                x1 = box->x1;
-            if (box->x2 < x2)
-                x2 = box->x2;
-
-            if (x2 <= x1)
-                continue;
-
-            if (y1 < box->y1)
-                y1 = box->y1;
-            if (box->y2 < y2)
-                y2 = box->y2;
-
-            if (y2 <= y1)
+            if (x2 <= x1 || y2 <= y1)
                 continue;
 
             glPixelStorei(GL_UNPACK_SKIP_ROWS, y1 - dy_dst + dy_src);
@@ -195,26 +182,14 @@ glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
         while (nbox--) {
 
             /* compute drawable coordinates */
-            int                     x1 = boxes->x1 + dx_src;
-            int                     x2 = boxes->x2 + dx_src;
-            int                     y1 = boxes->y1 + dy_src;
-            int                     y2 = boxes->y2 + dy_src;
+            int                     x1 = MAX(boxes->x1 + dx_src, box->x1);
+            int                     x2 = MIN(boxes->x2 + dx_src, box->x2);
+            int                     y1 = MAX(boxes->y1 + dy_src, box->y1);
+            int                     y2 = MIN(boxes->y2 + dy_src, box->y2);
 
             boxes++;
 
-            if (x1 < box->x1)
-                x1 = box->x1;
-            if (box->x2 < x2)
-                x2 = box->x2;
-
-            if (y1 < box->y1)
-                y1 = box->y1;
-            if (box->y2 < y2)
-                y2 = box->y2;
-
-            if (x2 <= x1)
-                continue;
-            if (y2 <= y1)
+            if (x2 <= x1 || y2 <= y1)
                 continue;
 
             glPixelStorei(GL_PACK_SKIP_PIXELS, x1 - dx_src + dx_dst);
commit 2ab0fba9df695f19f0b43321d01395736f865c69
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 2 13:41:09 2014 -0700

    glamor: Drop unnecessary glTexParameteri() in SetSpans().
    
    If this path needed the filters set, so would all the other
    glDrawArrays() callers.  But they don't.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_spans.c b/glamor/glamor_spans.c
index 46ba6c3..582d11d 100644
--- a/glamor/glamor_spans.c
+++ b/glamor/glamor_spans.c
@@ -326,9 +326,6 @@ glamor_set_spans_gl(DrawablePtr drawable, GCPtr gc, char *src,
 
     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);
-
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
     glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
commit e678b4971b666e65a99c141e0a5f33969aa701b7
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jul 15 17:31:59 2014 -0700

    xfree86: Provide backward-compatibilty API for OdevAttributes
    
    This allows drivers to compile using the old OdevAttributes API
    against a new server. It generates compiler errors if the caller uses
    the wrong or undefined attribute types, or if the caller provides an
    incorrect default value for an integer attribute.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 823a10c..2a90104 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -71,6 +71,77 @@ xf86_platform_odev_attributes(int index)
     return device->attribs;
 }
 
+#ifndef _XORG_CONFIG_H_
+/*
+ * Define the legacy API only for external builds
+ */
+
+/* path to kernel device node - Linux e.g. /dev/dri/card0 */
+#define ODEV_ATTRIB_PATH        1
+/* system device path - Linux e.g. /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 */
+#define ODEV_ATTRIB_SYSPATH     2
+/* DRI-style bus id */
+#define ODEV_ATTRIB_BUSID       3
+/* Server managed FD */
+#define ODEV_ATTRIB_FD          4
+/* Major number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MAJOR       5
+/* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MINOR       6
+/* kernel driver name */
+#define ODEV_ATTRIB_DRIVER      7
+
+/* Protect against a mismatch attribute type by generating a compiler
+ * error using a negative array size when an incorrect attribute is
+ * passed
+ */
+
+#define _ODEV_ATTRIB_IS_STRING(x)       ((x) == ODEV_ATTRIB_PATH ||     \
+                                         (x) == ODEV_ATTRIB_SYSPATH ||  \
+                                         (x) == ODEV_ATTRIB_BUSID ||    \
+                                         (x) == ODEV_ATTRIB_DRIVER)
+
+#define _ODEV_ATTRIB_STRING_CHECK(x)    ((int (*)[_ODEV_ATTRIB_IS_STRING(x)-1]) 0)
+
+static inline char *
+_xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib, int (*fake)[0])
+{
+    switch (attrib) {
+    case ODEV_ATTRIB_PATH:
+        return xf86_platform_device_odev_attributes(device)->path;
+    case ODEV_ATTRIB_SYSPATH:
+        return xf86_platform_device_odev_attributes(device)->syspath;
+    case ODEV_ATTRIB_BUSID:
+        return xf86_platform_device_odev_attributes(device)->busid;
+    case ODEV_ATTRIB_DRIVER:
+        return xf86_platform_device_odev_attributes(device)->driver;
+    }
+}
+
+#define xf86_get_platform_device_attrib(device, attrib) _xf86_get_platform_device_attrib(device,attrib,_ODEV_ATTRIB_STRING_CHECK(attrib))
+
+#define _ODEV_ATTRIB_IS_INT(x)                  ((x) == ODEV_ATTRIB_FD || (x) == ODEV_ATTRIB_MAJOR || (x) == ODEV_ATTRIB_MINOR)
+#define _ODEV_ATTRIB_INT_DEFAULT(x)             ((x) == ODEV_ATTRIB_FD ? -1 : 0)
+#define _ODEV_ATTRIB_DEFAULT_CHECK(x,def)       (_ODEV_ATTRIB_INT_DEFAULT(x) == (def))
+#define _ODEV_ATTRIB_INT_CHECK(x,def)           ((int (*)[_ODEV_ATTRIB_IS_INT(x)*_ODEV_ATTRIB_DEFAULT_CHECK(x,def)-1]) 0)
+
+static inline int
+_xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib, int (*fake)[0])
+{
+    switch (attrib) {
+    case ODEV_ATTRIB_FD:
+        return xf86_platform_device_odev_attributes(device)->fd;
+    case ODEV_ATTRIB_MAJOR:
+        return xf86_platform_device_odev_attributes(device)->major;
+    case ODEV_ATTRIB_MINOR:
+        return xf86_platform_device_odev_attributes(device)->minor;
+    }
+}
+
+#define xf86_get_platform_device_int_attrib(device, attrib, def) _xf86_get_platform_device_int_attrib(device,attrib,_ODEV_ATTRIB_INT_CHECK(attrib,def))
+
+#endif
+
 extern _X_EXPORT Bool
 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid);
 
commit 60c05ce1ab5d9dc7c034b6b3723f43a42ea637d8
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jul 15 17:31:58 2014 -0700

    config: Replace OdevAttributes linked list with struct
    
    OdevAttributes are a fixed set of values with known types; instead of
    storing them in a linked list and requiring accessor/settor functions,
    replace the list header, struct OdevAttributes, with a struct that
    directly contains the values. This provides for compile-time
    typechecking of the values, eliminates a significant amount of code
    and generally simplifies using this datatype.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/config/config.c b/config/config.c
index a26d835..b5d634b 100644
--- a/config/config.c
+++ b/config/config.c
@@ -128,160 +128,21 @@ device_is_duplicate(const char *config_info)
 }
 
 struct OdevAttributes *
-config_odev_allocate_attribute_list(void)
+config_odev_allocate_attributes(void)
 {
-    struct OdevAttributes *attriblist;
-
-    attriblist = XNFalloc(sizeof(struct OdevAttributes));
-    xorg_list_init(&attriblist->list);
-    return attriblist;
-}
-
-void
-config_odev_free_attribute_list(struct OdevAttributes *attribs)
-{
-    config_odev_free_attributes(attribs);
-    free(attribs);
-}
-
-static struct OdevAttribute *
-config_odev_find_attribute(struct OdevAttributes *attribs, int attrib_id)
-{
-    struct OdevAttribute *oa;
-
-    xorg_list_for_each_entry(oa, &attribs->list, member) {
-        if (oa->attrib_id == attrib_id)
-          return oa;
-    }
-    return NULL;
-}
-
-static struct OdevAttribute *
-config_odev_find_or_add_attribute(struct OdevAttributes *attribs, int attrib)
-{
-    struct OdevAttribute *oa;
-
-    oa = config_odev_find_attribute(attribs, attrib);
-    if (oa)
-        return oa;
-
-    oa = XNFcalloc(sizeof(struct OdevAttribute));
-    oa->attrib_id = attrib;
-    xorg_list_append(&oa->member, &attribs->list);
-
-    return oa;
-}
-
-static int config_odev_get_attribute_type(int attrib)
-{
-    switch (attrib) {
-    case ODEV_ATTRIB_PATH:
-    case ODEV_ATTRIB_SYSPATH:
-    case ODEV_ATTRIB_BUSID:
-        return ODEV_ATTRIB_STRING;
-    case ODEV_ATTRIB_FD:
-    case ODEV_ATTRIB_MAJOR:
-    case ODEV_ATTRIB_MINOR:
-        return ODEV_ATTRIB_INT;
-    case ODEV_ATTRIB_DRIVER:
-        return ODEV_ATTRIB_STRING;
-    default:
-        LogMessage(X_ERROR, "Error %s called for unknown attribute %d\n",
-                   __func__, attrib);
-        return ODEV_ATTRIB_UNKNOWN;
-    }
-}
-
-Bool
-config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
-                          const char *attrib_name)
-{
-    struct OdevAttribute *oa;
-
-    if (config_odev_get_attribute_type(attrib) != ODEV_ATTRIB_STRING) {
-        LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
-                   __func__, attrib);
-        return FALSE;
-    }
-
-    oa = config_odev_find_or_add_attribute(attribs, attrib);
-    free(oa->attrib_name);
-    oa->attrib_name = XNFstrdup(attrib_name);
-    oa->attrib_type = ODEV_ATTRIB_STRING;
-    return TRUE;
-}
-
-Bool
-config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
-                              int attrib_value)
-{
-    struct OdevAttribute *oa;
-
-    if (config_odev_get_attribute_type(attrib) != ODEV_ATTRIB_INT) {
-        LogMessage(X_ERROR, "Error %s called for non integer attrib %d\n",
-                   __func__, attrib);
-        return FALSE;
-    }
-
-    oa = config_odev_find_or_add_attribute(attribs, attrib);
-    oa->attrib_value = attrib_value;
-    oa->attrib_type = ODEV_ATTRIB_INT;
-    return TRUE;
-}
-
-char *
-config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id)
-{
-    struct OdevAttribute *oa;
-
-    oa = config_odev_find_attribute(attribs, attrib_id);
-    if (!oa)
-        return NULL;
-
-    if (oa->attrib_type != ODEV_ATTRIB_STRING) {
-        LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
-                   __func__, attrib_id);
-        return NULL;
-    }
-    return oa->attrib_name;
-}
-
-int
-config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib_id, int def)
-{
-    struct OdevAttribute *oa;
-
-    oa = config_odev_find_attribute(attribs, attrib_id);
-    if (!oa)
-        return def;
-
-    if (oa->attrib_type != ODEV_ATTRIB_INT) {
-        LogMessage(X_ERROR, "Error %s called for non integer attrib %d\n",
-                   __func__, attrib_id);
-        return def;
-    }
-
-    return oa->attrib_value;
+    struct OdevAttributes *attribs = XNFcalloc(sizeof (struct OdevAttributes));
+    attribs->fd = -1;
+    return attribs;
 }
 
 void
 config_odev_free_attributes(struct OdevAttributes *attribs)
 {
-    struct OdevAttribute *iter, *safe;
-    int major = 0, minor = 0, fd = -1;
-
-    xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) {
-        switch (iter->attrib_id) {
-        case ODEV_ATTRIB_MAJOR: major = iter->attrib_value; break;
-        case ODEV_ATTRIB_MINOR: minor = iter->attrib_value; break;
-        case ODEV_ATTRIB_FD: fd = iter->attrib_value; break;
-        }
-        xorg_list_del(&iter->member);
-        if (iter->attrib_type == ODEV_ATTRIB_STRING)
-            free(iter->attrib_name);
-        free(iter);
-    }
-
-    if (fd != -1)
-        systemd_logind_release_fd(major, minor, fd);
+    if (attribs->fd != -1)
+        systemd_logind_release_fd(attribs->major, attribs->minor, attribs->fd);
+    free(attribs->path);
+    free(attribs->syspath);
+    free(attribs->busid);
+    free(attribs->driver);
+    free(attribs);
 }
diff --git a/config/udev.c b/config/udev.c
index a1b72c1..1e4a9d7 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -462,12 +462,12 @@ config_udev_odev_setup_attribs(const char *path, const char *syspath,
                                int major, int minor,
                                config_odev_probe_proc_ptr probe_callback)
 {
-    struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
+    struct OdevAttributes *attribs = config_odev_allocate_attributes();
 
-    config_odev_add_attribute(attribs, ODEV_ATTRIB_PATH, path);
-    config_odev_add_attribute(attribs, ODEV_ATTRIB_SYSPATH, syspath);
-    config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
-    config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
+    attribs->path = XNFstrdup(path);
+    attribs->syspath = XNFstrdup(syspath);
+    attribs->major = major;
+    attribs->minor = minor;
 
     /* ownership of attribs is passed to probe layer */
     probe_callback(attribs);
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index eb1a3fb..22e4603 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -77,7 +77,7 @@ xf86_remove_platform_device(int dev_index)
 {
     int j;
 
-    config_odev_free_attribute_list(xf86_platform_devices[dev_index].attribs);
+    config_odev_free_attributes(xf86_platform_devices[dev_index].attribs);
 
     for (j = dev_index; j < xf86_num_platform_devices - 1; j++)
         memcpy(&xf86_platform_devices[j], &xf86_platform_devices[j + 1], sizeof(struct xf86_platform_device));
@@ -86,44 +86,6 @@ xf86_remove_platform_device(int dev_index)
 }
 
 Bool
-xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
-{
-    struct xf86_platform_device *device = &xf86_platform_devices[index];
-
-    return config_odev_add_attribute(device->attribs, attrib_id, attrib_name);
-}
-
-Bool
-xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value)
-{
-    return config_odev_add_int_attribute(xf86_platform_devices[index].attribs, attrib_id, attrib_value);
-}
-
-char *
-xf86_get_platform_attrib(int index, int attrib_id)
-{
-    return config_odev_get_attribute(xf86_platform_devices[index].attribs, attrib_id);
-}
-
-char *
-xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id)
-{
-    return config_odev_get_attribute(device->attribs, attrib_id);
-}
-
-int
-xf86_get_platform_int_attrib(int index, int attrib_id, int def)
-{
-    return config_odev_get_int_attribute(xf86_platform_devices[index].attribs, attrib_id, def);
-}
-
-int
-xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def)
-{
-    return config_odev_get_int_attribute(device->attribs, attrib_id, def);
-}
-
-Bool
 xf86_get_platform_device_unowned(int index)
 {
     return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ?
@@ -136,8 +98,8 @@ xf86_find_platform_device_by_devnum(int major, int minor)
     int i, attr_major, attr_minor;
 
     for (i = 0; i < xf86_num_platform_devices; i++) {
-        attr_major = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MAJOR, 0);
-        attr_minor = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MINOR, 0);
+        attr_major = xf86_platform_odev_attributes(i)->major;
+        attr_minor = xf86_platform_odev_attributes(i)->minor;
         if (attr_major == major && attr_minor == minor)
             return &xf86_platform_devices[i];
     }
@@ -240,7 +202,7 @@ MatchToken(const char *value, struct xorg_list *patterns,
 static Bool
 OutputClassMatches(const XF86ConfOutputClassPtr oclass, int index)
 {
-    char *driver = xf86_get_platform_attrib(index, ODEV_ATTRIB_DRIVER);
+    char *driver = xf86_platform_odev_attributes(index)->driver;
 
     if (!MatchToken(driver, &oclass->match_driver, strcmp))
         return FALSE;
@@ -259,7 +221,7 @@ xf86OutputClassDriverList(int index, char *matches[], int nmatches)
 
     for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) {
         if (OutputClassMatches(cl, index)) {
-            char *path = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH);
+            char *path = xf86_platform_odev_attributes(index)->path;
 
             xf86Msg(X_INFO, "Applying OutputClass \"%s\" to %s\n",
                     cl->identifier, path);
@@ -324,7 +286,7 @@ xf86platformProbe(void)
     }
 
     for (i = 0; i < xf86_num_platform_devices; i++) {
-        char *busid = xf86_get_platform_attrib(i, ODEV_ATTRIB_BUSID);
+        char *busid = xf86_platform_odev_attributes(i)->busid;
 
         if (pci && (strncmp(busid, "pci:", 4) == 0)) {
             platform_find_pci_info(&xf86_platform_devices[i], busid);
@@ -412,11 +374,11 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp,
     if (entity != -1) {
         if ((dev->flags & XF86_PDEV_SERVER_FD) && (!drvp->driverFunc ||
                 !drvp->driverFunc(NULL, SUPPORTS_SERVER_FDS, NULL))) {
-            fd = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_FD, -1);
-            major = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_MAJOR, 0);
-            minor = xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_MINOR, 0);
+            fd = dev->attribs->fd;
+            major = dev->attribs->major;
+            minor = dev->attribs->minor;
             systemd_logind_release_fd(major, minor, fd);
-            config_odev_add_int_attribute(dev->attribs, ODEV_ATTRIB_FD, -1);
+            dev->attribs->fd = -1;
             dev->flags &= ~XF86_PDEV_SERVER_FD;
         }
 
diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h
index 5dee4e0..823a10c 100644
--- a/hw/xfree86/common/xf86platformBus.h
+++ b/hw/xfree86/common/xf86platformBus.h
@@ -45,31 +45,32 @@ int xf86platformProbeDev(DriverPtr drvp);
 extern int xf86_num_platform_devices;
 extern struct xf86_platform_device *xf86_platform_devices;
 
-extern char *
-xf86_get_platform_attrib(int index, int attrib_id);
-extern int
-xf86_get_platform_int_attrib(int index, int attrib_id, int def);
 extern int
 xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned);
 extern int
 xf86_remove_platform_device(int dev_index);
 extern Bool
 xf86_get_platform_device_unowned(int index);
-/* Note starting with xserver 1.16 these 2 functions never fail */
-extern Bool
-xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
-extern Bool
-xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value);
 
 extern int
 xf86platformAddDevice(int index);
 extern void
 xf86platformRemoveDevice(int index);
 
-extern _X_EXPORT char *
-xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id);
-extern _X_EXPORT int
-xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def);
+static inline struct OdevAttributes *
+xf86_platform_device_odev_attributes(struct xf86_platform_device *device)
+{
+    return device->attribs;
+}
+
+static inline struct OdevAttributes *
+xf86_platform_odev_attributes(int index)
+{
+    struct xf86_platform_device *device = &xf86_platform_devices[index];
+
+    return device->attribs;
+}
+
 extern _X_EXPORT Bool
 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid);
 
diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index d660761..1d145b3 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -30,8 +30,8 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
     int err = 0;
     Bool paused, server_fd = FALSE;
 
-    major = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MAJOR, 0);
-    minor = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MINOR, 0);
+    major = attribs->major;
+    minor = attribs->minor;
 
     fd = systemd_logind_take_fd(major, minor, path, &paused);
     if (fd != -1) {
@@ -41,7 +41,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
             systemd_logind_release_fd(major, minor, -1);
             return FALSE;
         }
-        config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd);
+        attribs->fd = fd;
         server_fd = TRUE;
     }
 
@@ -73,8 +73,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
         xf86_platform_devices[delayed_index].flags |= XF86_PDEV_SERVER_FD;
 
     buf = drmGetBusid(fd);
-    xf86_add_platform_device_attrib(delayed_index,
-                                    ODEV_ATTRIB_BUSID, buf);
+    xf86_platform_odev_attributes(delayed_index)->busid = XNFstrdup(buf);
     drmFreeBusid(buf);
 
     v = drmGetVersion(fd);
@@ -83,8 +82,7 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
         goto out;
     }
 
-    xf86_add_platform_device_attrib(delayed_index, ODEV_ATTRIB_DRIVER,
-                                    v->name);
+    xf86_platform_odev_attributes(delayed_index)->driver = XNFstrdup(v->name);
     drmFreeVersion(v);
 
 out:
@@ -96,16 +94,9 @@ out:
 Bool
 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid)
 {
-    struct OdevAttribute *attrib;
-    const char *syspath = NULL;
+    const char *syspath = device->attribs->syspath;
     BusType bustype;
     const char *id;
-    xorg_list_for_each_entry(attrib, &device->attribs->list, member) {
-        if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) {
-            syspath = attrib->attrib_name;
-            break;
-        }
-    }
 
     if (!syspath)
         return FALSE;
@@ -138,8 +129,7 @@ void
 xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
 {
     Bool ret;
-    char *dpath;
-    dpath = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH);
+    char *dpath = attribs->path;
 
     ret = get_drm_info(attribs, dpath, index);
     if (ret == FALSE) {
@@ -155,18 +145,16 @@ void
 xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
 {
     int i;
-    char *path = NULL;
+    char *path = attribs->path;
     Bool ret;
 
-    path = config_odev_get_attribute(attribs, ODEV_ATTRIB_PATH);
     if (!path)
         goto out_free;
 
     for (i = 0; i < xf86_num_platform_devices; i++) {
-        char *dpath;
-        dpath = xf86_get_platform_attrib(i, ODEV_ATTRIB_PATH);
+        char *dpath = xf86_platform_odev_attributes(i)->path;
 
-        if (!strcmp(path, dpath))
+        if (dpath && !strcmp(path, dpath))
             break;
     }
 
@@ -189,7 +177,7 @@ xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
     return;
 
 out_free:
-    config_odev_free_attribute_list(attribs);
+    config_odev_free_attributes(attribs);
 }
 
 void NewGPUDeviceRequest(struct OdevAttributes *attribs)
@@ -214,21 +202,15 @@ void NewGPUDeviceRequest(struct OdevAttributes *attribs)
 
 void DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
 {
-    struct OdevAttribute *attrib;
     int index;
-    char *syspath = NULL;
+    char *syspath = attribs->syspath;
 
-    xorg_list_for_each_entry(attrib, &attribs->list, member) {
-        if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) {
-            syspath = attrib->attrib_name;
-            break;
-        }
-    }
+    if (!syspath)
+        goto out;
 
     for (index = 0; index < xf86_num_platform_devices; index++) {
-        char *dspath;
-        dspath = xf86_get_platform_attrib(index, ODEV_ATTRIB_SYSPATH);
-        if (!strcmp(syspath, dspath))
+        char *dspath = xf86_platform_odev_attributes(index)->syspath;
+        if (dspath && !strcmp(syspath, dspath))
             break;
     }
 
@@ -242,7 +224,7 @@ void DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
     else
             xf86platformRemoveDevice(index);
 out:
-    config_odev_free_attribute_list(attribs);
+    config_odev_free_attributes(attribs);
 }
 
 #endif
diff --git a/include/hotplug.h b/include/hotplug.h
index 4c2fa97..6fe76c8 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -32,64 +32,41 @@ extern _X_EXPORT void config_pre_init(void);
 extern _X_EXPORT void config_init(void);
 extern _X_EXPORT void config_fini(void);
 
-enum { ODEV_ATTRIB_UNKNOWN = -1, ODEV_ATTRIB_STRING = 0, ODEV_ATTRIB_INT };
-
-struct OdevAttribute {
-    struct xorg_list member;
-    int attrib_id;
-    union {
-        char *attrib_name;
-        int attrib_value;
-    };
-    int attrib_type;
-};
+/* Bump this each time you add something to the struct
+ * so that drivers can easily tell what is available
+ */
+#define ODEV_ATTRIBUTES_VERSION         1
 
 struct OdevAttributes {
-    struct xorg_list list;
-};
+    /* path to kernel device node - Linux e.g. /dev/dri/card0 */
+    char        *path;
 
-/* Note starting with xserver 1.16 this function never fails */
-struct OdevAttributes *
-config_odev_allocate_attribute_list(void);
+    /* system device path - Linux e.g. /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 */
+    char        *syspath;
 
-void
-config_odev_free_attribute_list(struct OdevAttributes *attribs);
+    /* DRI-style bus id */
+    char        *busid;
 
-/* Note starting with xserver 1.16 this function never fails */
-Bool
-config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
-                          const char *attrib_name);
+    /* Server managed FD */
+    int         fd;
 
-char *
-config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
+    /* Major number of the device node pointed to by ODEV_ATTRIB_PATH */
+    int         major;
 
-/* Note starting with xserver 1.16 this function never fails */
-Bool
-config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
-                              int attrib_value);
+    /* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
+    int         minor;
+
+    /* kernel driver name */
+    char        *driver;
+};
 
-int
-config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib,
-                              int def);
+/* Note starting with xserver 1.16 this function never fails */
+struct OdevAttributes *
+config_odev_allocate_attributes(void);
 
 void
 config_odev_free_attributes(struct OdevAttributes *attribs);
 
-/* path to kernel device node - Linux e.g. /dev/dri/card0 */
-#define ODEV_ATTRIB_PATH 1
-/* system device path - Linux e.g. /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card1 */
-#define ODEV_ATTRIB_SYSPATH 2
-/* DRI-style bus id */
-#define ODEV_ATTRIB_BUSID 3
-/* Server managed FD */
-#define ODEV_ATTRIB_FD 4
-/* Major number of the device node pointed to by ODEV_ATTRIB_PATH */
-#define ODEV_ATTRIB_MAJOR 5
-/* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
-#define ODEV_ATTRIB_MINOR 6
-/* kernel driver name */
-#define ODEV_ATTRIB_DRIVER 7
-
 typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
 void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
 
commit 55f5bfb578e934319d1308cbb56c900c5ac7cfa7
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Jul 16 16:03:23 2014 -0700

    glamor: Fix temp picture coordinates in glamor_composite_clipped_region
    
    To understand this patch, let's start at the protocol interface where
    the relationship between the coordinate spaces is documented:
    
            static Bool
            _glamor_composite(CARD8 op,
                              PicturePtr source,
                              PicturePtr mask,
                              PicturePtr dest,
                              INT16 x_source,
                              INT16 y_source,
                              INT16 x_mask,
                              INT16 y_mask,
                              INT16 x_dest, INT16 y_dest,
                              CARD16 width, CARD16 height, Bool fallback)
    
    The coordinates are passed to this function directly off the wire and
    are all relative to their respective drawables. For Windows, this means
    that they are relative to the upper left corner of the window, in
    whatever pixmap that window is getting drawn to.
    
    _glamor_composite calls miComputeCompositeRegion to construct a clipped
    region to actually render to. In reality, miComputeCompositeRegion clips
    only to the destination these days; source clip region based clipping
    would have to respect the transform, which isn't really possible. The
    returned region is relative to the screen in which dest lives; offset by
    dest->drawable.x and dest->drawable.y.
    
    What is important to realize here is that, because of clipping, the
    composite region may not have the same position within the destination
    drawable as x_dest, y_dest. The protocol coordinates now exist solely to
    'pin' the three objects together.
    
            extents->x1,y1		Screen origin of clipped operation
            width,height            Extents of the clipped operation
            x_dest,y_dest		Unclipped destination-relative operation coordinate
            x_source,y_source	Unclipped source-relative operation coordinate
            x_mask,y_mask		Unclipped mask-relative operation coordinate
    
    One thing we want to know is what the offset is from the original
    operation origin to the clipped origin
    
            Destination drawable relative coordinates of the clipped operation:
    
                   x_dest_clipped = extents->x1 - dest->drawable.x
                   y_dest_clipped = extents->y1 - dest->drawable.y
    
            Offset from the original operation origin:
    
                    x_off_clipped = x_dest_clipped - x_dest
                    y_off_clipped = y_dest_clipped - y_dest
    
            Source drawable relative coordinates of the clipped operation:
    
                    x_source_clipped = x_source + x_off_clipped;
                    y_source_clipped = y_source + y_off_clipped;
    
            Mask drawable relative coordinates of the clipped operation:
    
                    x_mask_clipped = x_source + x_off_clipped;
                    y_mask_clipped = y_source + y_off_clipped;
    
    This is where the original code fails -- it doesn't subtract the
    destination drawable location when computing the distance that the
    operation has been moved by clipping. Here's what it does when
    constructing a temporary source picture:
    
            temp_src =
                glamor_convert_gradient_picture(screen, source,
                                                extent->x1 + x_source - x_dest,
                                                extent->y1 + y_source - y_dest,
                                                width, height);
            ...
            x_temp_src = -extent->x1 + x_dest;
            y_temp_src = -extent->y1 + y_dest;
    
    glamor_convert_gradient_picture needs source drawable relative
    coordinates, but that is not what it's getting; it's getting
    screen-relative coordinates for the destination, adjusted by the
    distance between the provided source and destination operation
    coordinates. We want x_source_clipped and y_source_clipped:
    
            x_source_clipped = x_source + x_off_clipped
                             = x_source + x_dest_clipped - x_dest
                             = x_source + extents->x1 - dest->drawable.x - x_dest
    
    x_temp_src/y_temp_src are supposed to be the coordinates of the original
    operation translated to the temporary picture:
    
            x_temp_src = x_source - x_source_clipped;
            y_temp_src = y_source - y_source_clipped;
    
    Note that x_source_clipped/y_source_clipped will never be less than
    x_source/y_source because all we're doing is clipping. This means that
    x_temp_src/y_temp_src will always be non-positive; the original source
    coordinate can never be strictly *inside* the temporary image or we
    could have made the temporary image smaller.
    
            x_temp_src = x_source - x_source_clipped
                       = x_source - (x_source + x_off_clipped)
                       = -x_off_clipped
                       = x_dest - x_dest_clipped
                       = x_dest - (extents->x1 - dest->drawable.x)
    
    Again, this is off by the destination origin within the screen
    coordinate space.
    
    The code should look like:
    
            temp_src =
                glamor_convert_gradient_picture(screen, source,
                                                extent->x1 + x_source - x_dest - dest->pDrawable->x,
                                                extent->y1 + y_source - y_dest - dest->pDrawable->y,
                                                width, height);
    
            x_temp_src = -extent->x1 + x_dest + dest->pDrawable->x;
            y_temp_src = -extent->y1 + y_dest + dest->pDrawable->y;
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 14ab738..e5d5d2c 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,
+                                            extent->x1 + x_source - x_dest - dest->pDrawable->x,
+                                            extent->y1 + y_source - y_dest - dest->pDrawable->y,
                                             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 = -extent->x1 + x_dest + dest->pDrawable->x;
+        y_temp_src = -extent->y1 + y_dest + dest->pDrawable->y;
     }
 
     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,
+                                            extent->x1 + x_mask - x_dest - dest->pDrawable->x,
+                                            extent->y1 + y_mask - y_dest - dest->pDrawable->y,
                                             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 = -extent->x1 + x_dest + dest->pDrawable->x;
+        y_temp_mask = -extent->y1 + y_dest + dest->pDrawable->y;
     }
     /* Do two-pass PictOpOver componentAlpha, until we enable
      * dual source color blending.
commit 16fbad3c7a22d2fb33549bcd422de985a60982b8
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 17 16:17:53 2014 -0700

    Post 1.16 version bump to 1.16.99.1
    
    And we're off towards 1.17; this version bump serves to keep
    development versions distinct from stable versions.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 1c327fd..4338dc5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.16.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2014-07-16"
-RELEASE_NAME="Marionberry Pie"
+AC_INIT([xorg-server], 1.16.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2014-07-17"
+RELEASE_NAME="Baba Ghanouj"
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
commit bfa5c73a36230f77fb211f185152212541c9d56d
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Jun 4 22:00:45 2014 -0700

    ephyr: Free damage structure at server reset time
    
    The usual mechanism for freeing a damage structure when the pixmap is
    destroyed does not work for the screen pixmap as it isn't freed in the
    normal way.
    
    The existing driver cleanup function, scrfini, is called after the
    wrapped CloseScreen functions, including damageCloseScreen, are called
    and thus ephyr can't free the damage structure at that point.
    
    Deal with this by providing an early CloseScreen hook in KdCloseScreen
    which ephyr can use to free the damage structure before damage itself
    shuts down.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Jamey Sharp <jamey at minilop.net>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index def50d8..49a4d2d 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -756,6 +756,12 @@ ephyrScreenFini(KdScreenInfo * screen)
     }
 }
 
+void
+ephyrCloseScreen(ScreenPtr pScreen)
+{
+    ephyrUnsetInternalDamage(pScreen);
+}
+
 /*  
  * Port of Mark McLoughlin's Xnest fix for focus in + modifier bug.
  * See https://bugs.freedesktop.org/show_bug.cgi?id=3030
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 34ce460..e691780 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -131,6 +131,9 @@ void
  ephyrScreenFini(KdScreenInfo * screen);
 
 void
+ephyrCloseScreen(ScreenPtr pScreen);
+
+void
  ephyrCardFini(KdCardInfo * card);
 
 void
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index fac84cd..3f66e1c 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -430,4 +430,6 @@ KdCardFuncs ephyrFuncs = {
 
     ephyrGetColors,             /* getColors */
     ephyrPutColors,             /* putColors */
+
+    ephyrCloseScreen,           /* closeScreen */
 };
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index 9814fc6..b5b91c0 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -621,8 +621,12 @@ KdCloseScreen(ScreenPtr pScreen)
     KdCardInfo *card = pScreenPriv->card;
     Bool ret;
 
+    if (card->cfuncs->closeScreen)
+        (*card->cfuncs->closeScreen)(pScreen);
+
     pScreenPriv->closed = TRUE;
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
+
     if (pScreen->CloseScreen)
         ret = (*pScreen->CloseScreen) (pScreen);
     else
diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h
index bec75cb..08b1681 100644
--- a/hw/kdrive/src/kdrive.h
+++ b/hw/kdrive/src/kdrive.h
@@ -130,6 +130,7 @@ typedef struct _KdCardFuncs {
     void (*getColors) (ScreenPtr, int, xColorItem *);
     void (*putColors) (ScreenPtr, int, xColorItem *);
 
+    void (*closeScreen) (ScreenPtr);    /* close ScreenRec */
 } KdCardFuncs;
 
 #define KD_MAX_PSEUDO_DEPTH 8
commit 3319e7041ff89bb01b16a1dbbac85e28b1976ae3
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 18 14:24:29 2014 -0700

    hw/xfree86: Let xf86Rotate leave the BlockHandler unwrapped when possible
    
    When no shadow frame buffer is needed, the rotate block handler
    doesn't need to be called any more. Remove it from the chain.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 99dcb43..1627e61 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -243,9 +243,13 @@ xf86RotateBlockHandler(ScreenPtr pScreen,
     xf86RotateRedisplay(pScreen);
 
     (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
-    /* cannot avoid re-wrapping until all wrapping is audited */
-    xf86_config->BlockHandler = pScreen->BlockHandler;
-    pScreen->BlockHandler = xf86RotateBlockHandler;
+
+    /* Re-wrap if we still need this hook */
+    if (xf86_config->rotation_damage != NULL) {
+        xf86_config->BlockHandler = pScreen->BlockHandler;
+        pScreen->BlockHandler = xf86RotateBlockHandler;
+    } else
+        xf86_config->BlockHandler = NULL;
 }
 
 void
commit 79a2733005202af43821d8fd8e4c9fb77bf8f69e
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 18 14:11:17 2014 -0700

    hw/xfree86: Fix VGA arbiter screen proc wrapping
    
    Change the screen proc epilog code to re-fetch the current screen
    function in case a nested proc changes how things work. This isn't a
    problem with the current code as all of the wrapping layers that are
    set up at server init time (like the VGA arbiter) leave themselves in
    the screen proc chain forever. But, this makes the code conform with
    the expected norms.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/xfree86/common/xf86VGAarbiterPriv.h b/hw/xfree86/common/xf86VGAarbiterPriv.h
index ec21bc2..b832c9a 100644
--- a/hw/xfree86/common/xf86VGAarbiterPriv.h
+++ b/hw/xfree86/common/xf86VGAarbiterPriv.h
@@ -49,10 +49,14 @@
 
 #define UNWRAP_SCREEN(x) pScreen->x = pScreenPriv->x
 
-#define SCREEN_PROLOG(x) pScreen->x = ((VGAarbiterScreenPtr) \
-    dixLookupPrivate(&(pScreen)->devPrivates, VGAarbiterScreenKey))->x
+#define SCREEN_PRIV()   ((VGAarbiterScreenPtr) dixLookupPrivate(&(pScreen)->devPrivates, VGAarbiterScreenKey))
 
-#define SCREEN_EPILOG(x,y) pScreen->x = y;
+#define SCREEN_PROLOG(x) (pScreen->x = SCREEN_PRIV()->x)
+
+#define SCREEN_EPILOG(x,y) do {                 \
+        SCREEN_PRIV()->x = pScreen->x;          \
+        pScreen->x = y;                         \
+    } while (0)
 
 #define WRAP_PICT(x,y) if (ps) {pScreenPriv->x = ps->x;\
     ps->x = y;}
commit a1189fe322724ab1b524aaad5b700287777252bd
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 18 13:57:55 2014 -0700

    mi: Fix block handler wrapping in miSprite
    
    miSpriteBlockHandler was leaving the BlockHandler wrapped until just
    before calling any nested block handler. If any code executed before
    that added or removed block handlers, the wrapping chain would have
    been broken.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/mi/misprite.c b/mi/misprite.c
index eea731a..68a49be 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -520,6 +520,8 @@ miSpriteBlockHandler(ScreenPtr pScreen, void *pTimeout,
     miCursorInfoPtr pCursorInfo;
     Bool WorkToDo = FALSE;
 
+    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
+
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
         if (DevHasCursor(pDev)) {
             pCursorInfo = MISPRITE(pDev);
@@ -543,8 +545,6 @@ miSpriteBlockHandler(ScreenPtr pScreen, void *pTimeout,
         }
     }
 
-    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
-
     (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
 
     if (WorkToDo)
commit 08fc33042c858568e7244eb9ad25a8d0270754f0
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 18 13:55:50 2014 -0700

    hw/xfree86: Fix block handler wrapping in xf86Rotate
    
    xf86Rotate, it was delaying unwrapping the BlockHandler until after
    calling xf86RotateRedisplay. If there was a software cursor on the
    screen, the redisplay operation would cause cursor to be removed from
    the frame buffer and the misprite block handler to be inserted into
    the block handler chain with the misprite screen private saved block
    handler now set to xf86RotateBlockHandler.
    
    When xf86RotateRedisplay returned, xf86RotateBlockHandler would then
    set screen->BlockHandler to its saved value, call down and then reset
    screen->BlockHandler to xf86RotateBlockHandler. miSpriteBlockHandler
    would never be called after that, which meant that the software cursor
    will now disappear from the screen whenever rendering overlapped and
    would only reappear when the cursor was moved.
    
    To correct this, all that is needed is to move the restoration of
    screen->BlockHandler to the top of xf86RotateBlockHandler, before the
    call to xf86RotateRedisplay.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 0ddd840..99dcb43 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -234,8 +234,14 @@ xf86RotateBlockHandler(ScreenPtr pScreen,
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
-    xf86RotateRedisplay(pScreen);
+    /* Unwrap before redisplay in case the software
+     * cursor layer wants to add its block handler to the
+     * chain
+     */
     pScreen->BlockHandler = xf86_config->BlockHandler;
+
+    xf86RotateRedisplay(pScreen);
+
     (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
     /* cannot avoid re-wrapping until all wrapping is audited */
     xf86_config->BlockHandler = pScreen->BlockHandler;
commit c75fee79ace394f6f51aa6fdda1c0436eb8a2026
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 18 13:54:11 2014 -0700

    Document how to correctly wrap screen procedures
    
    This adds a large comment to include/scrnintstr.h which should serve
    to document the correct way to wrap any screen procedure, with a
    particular focus on how to dynamically add/remove wrapping layers
    while the server is running.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 5312781..6955e77 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -358,6 +358,96 @@ typedef WindowPtr (*XYToWindowProcPtr)(ScreenPtr pScreen,
 
 typedef int (*NameWindowPixmapProcPtr)(WindowPtr, PixmapPtr, CARD32);
 
+/* Wrapping Screen procedures
+
+   There are a few modules in the X server which dynamically add and
+    remove themselves from various screen procedure call chains.
+
+    For example, the BlockHandler is dynamically modified by:
+
+     * xf86Rotate
+     * miSprite
+     * composite
+     * render (for animated cursors)
+
+    Correctly manipulating this chain is complicated by the fact that
+    the chain is constructed through a sequence of screen private
+    structures, each holding the next screen->proc pointer.
+
+    To add a module to a screen->proc chain is fairly simple; just save
+    the current screen->proc value in the module screen private
+    and store the module's function in the screen->proc location.
+
+    Removing a screen proc is a bit trickier. It seems like all you
+    need to do is set the screen->proc pointer back to the value saved
+    in your screen private. However, if some other module has come
+    along and wrapped on top of you, then the right place to store the
+    previous screen->proc value is actually in the wrapping module's
+    screen private structure(!). Of course, you have no idea what
+    other module may have wrapped on top, nor could you poke inside
+    its screen private in any case.
+
+    To make this work, we restrict the unwrapping process to happen
+    during the invocation of the screen proc itself, and then we
+    require the screen proc to take some care when manipulating the
+    screen proc functions pointers.
+
+    The requirements are:
+
+     1) The screen proc must set the screen->proc pointer back to the
+        value saved in its screen private before calling outside its
+        module.
+
+     2a) If the screen proc wants to be remove itself from the chain,
+         it must not manipulate screen->proc pointer again before
+         returning.
+
+     2b) If the screen proc wants to remain in the chain, it must:
+
+       2b.1) Re-fetch the screen->proc pointer and store that in
+             its screen private. This ensures that any changes
+             to the chain will be preserved.
+
+       2b.2) Set screen->proc back to itself
+
+    One key requirement here is that these steps must wrap not just
+    any invocation of the nested screen->proc value, but must nest
+    essentially any calls outside the current module. This ensures
+    that other modules can reliably manipulate screen->proc wrapping
+    using these same rules.
+
+    For example, the animated cursor code in render has two macros,
+    Wrap and Unwrap.
+
+        #define Unwrap(as,s,elt)    ((s)->elt = (as)->elt)
+
+    Unwrap takes the screen private (as), the screen (s) and the
+    member name (elt), and restores screen->proc to that saved in the
+    screen private.
+
+        #define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
+
+    Wrap takes the screen private (as), the screen (s), the member
+    name (elt) and the wrapping function (func). It saves the
+    current screen->proc value in the screen private, and then sets the
+    screen->proc to the local wrapping function.
+
+    Within each of these functions, there's a pretty simple pattern:
+
+        Unwrap(as, pScreen, UnrealizeCursor);
+
+        // Do local stuff, including possibly calling down through
+        // pScreen->UnrealizeCursor
+
+        Wrap(as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
+
+    The wrapping block handler is a bit different; it does the Unwrap,
+    the local operations and then only re-Wraps if the hook is still
+    required. Unwrap occurrs at the top of each function, just after
+    entry, and Wrap occurrs at the bottom of each function, just
+    before returning.
+ */
+
 typedef struct _Screen {
     int myNum;                  /* index of this instance in Screens[] */
     ATOM id;
commit 5eb77697ea35e7dc8cb8af2c3b5d8ffdba0fb632
Author: Peter Harris <pharris at opentext.com>
Date:   Mon Mar 10 18:31:33 2014 -0400

    Avoid starting a comment with */*
    
    Even though -Wcomment doesn't mind it (in gcc or clang), the appearance
    of */* confuses the syntax highlighter of some editors (eg. vim), and
    causes warnings in MSVC.
    
    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/include/callback.h b/include/callback.h
index df638c0..fe7015e 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -64,16 +64,16 @@ typedef struct _CallbackList *CallbackListPtr;  /* also in misc.h */
 
 typedef void (*CallbackProcPtr) (CallbackListPtr *, void *, void *);
 
-extern _X_EXPORT Bool AddCallback(CallbackListPtr * /*pcbl */ ,
-                                  CallbackProcPtr /*callback */ ,
-                                  void */*data */ );
+extern _X_EXPORT Bool AddCallback(CallbackListPtr *pcbl,
+                                  CallbackProcPtr callback,
+                                  void *data);
 
-extern _X_EXPORT Bool DeleteCallback(CallbackListPtr * /*pcbl */ ,
-                                     CallbackProcPtr /*callback */ ,
-                                     void */*data */ );
+extern _X_EXPORT Bool DeleteCallback(CallbackListPtr *pcbl,
+                                     CallbackProcPtr callback,
+                                     void *data);
 
-extern _X_EXPORT void _CallCallbacks(CallbackListPtr * /*pcbl */ ,
-                                     void */*call_data */ );
+extern _X_EXPORT void _CallCallbacks(CallbackListPtr *pcbl,
+                                     void *call_data);
 
 static inline void
 CallCallbacks(CallbackListPtr *pcbl, void *call_data)
@@ -83,7 +83,7 @@ CallCallbacks(CallbackListPtr *pcbl, void *call_data)
     _CallCallbacks(pcbl, call_data);
 }
 
-extern _X_EXPORT void DeleteCallbackList(CallbackListPtr * /*pcbl */ );
+extern _X_EXPORT void DeleteCallbackList(CallbackListPtr *pcbl);
 
 extern _X_EXPORT void InitCallbackManager(void);
 extern _X_EXPORT void DeleteCallbackManager(void);
diff --git a/include/colormap.h b/include/colormap.h
index 22229ca..b89bbe1 100644
--- a/include/colormap.h
+++ b/include/colormap.h
@@ -82,14 +82,14 @@ extern _X_EXPORT int CreateColormap(Colormap /*mid */ ,
                                     int /*alloc */ ,
                                     int /*client */ );
 
-extern _X_EXPORT int FreeColormap(void */*pmap */ ,
-                                  XID /*mid */ );
+extern _X_EXPORT int FreeColormap(void *pmap,
+                                  XID mid);
 
-extern _X_EXPORT int TellLostMap(WindowPtr /*pwin */ ,
-                                 void */* Colormap *pmid */ );
+extern _X_EXPORT int TellLostMap(WindowPtr pwin,
+                                 void *value);
 
-extern _X_EXPORT int TellGainedMap(WindowPtr /*pwin */ ,
-                                   void */* Colormap *pmid */ );
+extern _X_EXPORT int TellGainedMap(WindowPtr pwin,
+                                   void *value);
 
 extern _X_EXPORT int CopyColormapAndFree(Colormap /*mid */ ,
                                          ColormapPtr /*pSrc */ ,
@@ -126,8 +126,8 @@ extern _X_EXPORT int QueryColors(ColormapPtr /*pmap */ ,
                                  xrgb * /*prgbList */ ,
                                  ClientPtr client);
 
-extern _X_EXPORT int FreeClientPixels(void */*pcr */ ,
-                                      XID /*fakeid */ );
+extern _X_EXPORT int FreeClientPixels(void *pcr,
+                                      XID fakeid);
 
 extern _X_EXPORT int AllocColorCells(int /*client */ ,
                                      ColormapPtr /*pmap */ ,
diff --git a/include/cursor.h b/include/cursor.h
index 9da08af..1e483ac 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -68,8 +68,8 @@ extern _X_EXPORT DevScreenPrivateKeyRec cursorScreenDevPriv;
 
 extern _X_EXPORT CursorPtr rootCursor;
 
-extern _X_EXPORT int FreeCursor(void */*pCurs */ ,
-                                XID /*cid */ );
+extern _X_EXPORT int FreeCursor(void *pCurs,
+                                XID cid);
 
 extern _X_EXPORT CursorPtr RefCursor(CursorPtr /* cursor */);
 extern _X_EXPORT CursorPtr UnrefCursor(CursorPtr /* cursor */);
diff --git a/include/dix.h b/include/dix.h
index f42e236..61ecc8d 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -147,14 +147,14 @@ extern _X_EXPORT void UpdateCurrentTime(void);
 
 extern _X_EXPORT void UpdateCurrentTimeIf(void);
 
-extern _X_EXPORT int dixDestroyPixmap(void */*value */ ,
-                                      XID /*pid */ );
+extern _X_EXPORT int dixDestroyPixmap(void *value,
+                                      XID pid);
 
-extern _X_EXPORT void InitClient(ClientPtr /*client */ ,
-                                 int /*i */ ,
-                                 void */*ospriv */ );
+extern _X_EXPORT void InitClient(ClientPtr client,
+                                 int i,
+                                 void *ospriv);
 
-extern _X_EXPORT ClientPtr NextAvailableClient(void */*ospriv */ );
+extern _X_EXPORT ClientPtr NextAvailableClient(void *ospriv);
 
 extern _X_EXPORT void SendErrorToClient(ClientPtr /*client */ ,
                                         unsigned int /*majorCode */ ,
@@ -203,11 +203,11 @@ extern _X_EXPORT int AlterSaveSetForClient(ClientPtr /*client */ ,
 
 extern _X_EXPORT void DeleteWindowFromAnySaveSet(WindowPtr /*pWin */ );
 
-extern _X_EXPORT void BlockHandler(void */*pTimeout */ ,
-                                   void */*pReadmask */ );
+extern _X_EXPORT void BlockHandler(void *pTimeout,
+                                   void *pReadmask);
 
-extern _X_EXPORT void WakeupHandler(int /*result */ ,
-                                    void */*pReadmask */ );
+extern _X_EXPORT void WakeupHandler(int result,
+                                    void *pReadmask);
 
 void
  EnableLimitedSchedulingLatency(void);
@@ -215,21 +215,17 @@ void
 void
  DisableLimitedSchedulingLatency(void);
 
-typedef void (*WakeupHandlerProcPtr) (void */* blockData */ ,
-                                      int /* result */ ,
-                                      void */* pReadmask */ );
+typedef void (*WakeupHandlerProcPtr) (void *blockData,
+                                      int result,
+                                      void *pReadmask);
 
-extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(BlockHandlerProcPtr
-                                                     /*blockHandler */ ,
-                                                     WakeupHandlerProcPtr
-                                                     /*wakeupHandler */ ,
-                                                     void */*blockData */ );
+extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(BlockHandlerProcPtr blockHandler,
+                                                     WakeupHandlerProcPtr wakeupHandler,
+                                                     void *blockData);
 
-extern _X_EXPORT void RemoveBlockAndWakeupHandlers(BlockHandlerProcPtr
-                                                   /*blockHandler */ ,
-                                                   WakeupHandlerProcPtr
-                                                   /*wakeupHandler */ ,
-                                                   void */*blockData */ );
+extern _X_EXPORT void RemoveBlockAndWakeupHandlers(BlockHandlerProcPtr blockHandler,
+                                                   WakeupHandlerProcPtr wakeupHandler,
+                                                   void *blockData);
 
 extern _X_EXPORT void InitBlockAndWakeupHandlers(void);
 
@@ -237,22 +233,17 @@ extern _X_EXPORT void ProcessWorkQueue(void);
 
 extern _X_EXPORT void ProcessWorkQueueZombies(void);
 
-extern _X_EXPORT Bool QueueWorkProc(Bool (* /*function */ )(
-                                                               ClientPtr
-                                                               /*clientUnused */
-                                                               ,
-                                                               void *
-                                                               /*closure */ ),
-                                    ClientPtr /*client */ ,
-                                    void */*closure */
-    );
+extern _X_EXPORT Bool QueueWorkProc(Bool (*function)(ClientPtr clientUnused,
+                                                     void *closure),
+                                    ClientPtr client,
+                                    void *closure);
 
-typedef Bool (*ClientSleepProcPtr) (ClientPtr /*client */ ,
-                                    void */*closure */ );
+typedef Bool (*ClientSleepProcPtr) (ClientPtr client,
+                                    void *closure);
 
-extern _X_EXPORT Bool ClientSleep(ClientPtr /*client */ ,
-                                  ClientSleepProcPtr /* function */ ,
-                                  void */*closure */ );
+extern _X_EXPORT Bool ClientSleep(ClientPtr client,
+                                  ClientSleepProcPtr function,
+                                  void *closure);
 
 #ifndef ___CLIENTSIGNAL_DEFINED___
 #define ___CLIENTSIGNAL_DEFINED___
@@ -444,8 +435,8 @@ extern void
 RecalculateDeliverableEvents(WindowPtr /* pWin */ );
 
 extern _X_EXPORT int
-OtherClientGone(void */* value */ ,
-                XID /* id */ );
+OtherClientGone(void *value,
+                XID id);
 
 extern void
 DoFocusEvents(DeviceIntPtr /* dev */ ,
diff --git a/include/dixfont.h b/include/dixfont.h
index 40d80c1..48c6305 100644
--- a/include/dixfont.h
+++ b/include/dixfont.h
@@ -40,9 +40,9 @@ extern _X_EXPORT void QueueFontWakeup(FontPathElementPtr /*fpe */ );
 
 extern _X_EXPORT void RemoveFontWakeup(FontPathElementPtr /*fpe */ );
 
-extern _X_EXPORT void FontWakeup(void */*data */ ,
-                                 int /*count */ ,
-                                 void */*LastSelectMask */ );
+extern _X_EXPORT void FontWakeup(void *data,
+                                 int count,
+                                 void *LastSelectMask);
 
 extern _X_EXPORT int OpenFont(ClientPtr /*client */ ,
                               XID /*fid */ ,
@@ -50,8 +50,8 @@ extern _X_EXPORT int OpenFont(ClientPtr /*client */ ,
                               unsigned /*lenfname */ ,
                               const char * /*pfontname */ );
 
-extern _X_EXPORT int CloseFont(void */*pfont */ ,
-                               XID /*fid */ );
+extern _X_EXPORT int CloseFont(void *pfont,
+                               XID fid);
 
 typedef struct _xQueryFontReply *xQueryFontReplyPtr;
 
diff --git a/include/dixgrabs.h b/include/dixgrabs.h
index d78d812..3bd8013 100644
--- a/include/dixgrabs.h
+++ b/include/dixgrabs.h
@@ -47,8 +47,8 @@ extern GrabPtr CreateGrab(int /* client */ ,
                           WindowPtr /* confineTo */ ,
                           CursorPtr /* cursor */ );
 
-extern _X_EXPORT int DeletePassiveGrab(void */* value */ ,
-                                       XID /* id */ );
+extern _X_EXPORT int DeletePassiveGrab(void *value,
+                                       XID id);
 
 extern _X_EXPORT Bool GrabMatchesSecond(GrabPtr /* pFirstGrab */ ,
                                         GrabPtr /* pSecondGrab */ ,
diff --git a/include/gc.h b/include/gc.h
index ecaa257..eb0a583 100644
--- a/include/gc.h
+++ b/include/gc.h
@@ -112,8 +112,8 @@ extern _X_EXPORT int CopyGC(GCPtr /*pgcSrc */ ,
                             GCPtr /*pgcDst */ ,
                             BITS32 /*mask */ );
 
-extern _X_EXPORT int FreeGC(void */*pGC */ ,
-                            XID /*gid */ );
+extern _X_EXPORT int FreeGC(void *pGC,
+                            XID gid);
 
 extern _X_EXPORT void FreeGCperDepth(int /*screenNum */ );
 
diff --git a/include/gcstruct.h b/include/gcstruct.h
index c830ccd..6358b8c 100644
--- a/include/gcstruct.h
+++ b/include/gcstruct.h
@@ -76,10 +76,10 @@ typedef struct _GCFuncs {
 
     void (*DestroyGC) (GCPtr /*pGC */ );
 
-    void (*ChangeClip) (GCPtr /*pGC */ ,
-                        int /*type */ ,
-                        void */*pvalue */ ,
-                        int /*nrects */ );
+    void (*ChangeClip) (GCPtr pGC,
+                        int type,
+                        void *pvalue,
+                        int nrects);
 
     void (*DestroyClip) (GCPtr /*pGC */ );
 
@@ -210,21 +210,21 @@ typedef struct _GCOps {
                          int /*count */ ,
                          unsigned short * /*chars */ );
 
-    void (*ImageGlyphBlt) (DrawablePtr /*pDrawable */ ,
-                           GCPtr /*pGC */ ,
-                           int /*x */ ,
-                           int /*y */ ,
-                           unsigned int /*nglyph */ ,
-                           CharInfoPtr * /*ppci */ ,
-                           void */*pglyphBase */ );
-
-    void (*PolyGlyphBlt) (DrawablePtr /*pDrawable */ ,
-                          GCPtr /*pGC */ ,
-                          int /*x */ ,
-                          int /*y */ ,
-                          unsigned int /*nglyph */ ,
-                          CharInfoPtr * /*ppci */ ,
-                          void */*pglyphBase */ );
+    void (*ImageGlyphBlt) (DrawablePtr pDrawable,
+                           GCPtr pGC,
+                           int x,
+                           int y,
+                           unsigned int nglyph,
+                           CharInfoPtr *ppci,
+                           void *pglyphBase);
+
+    void (*PolyGlyphBlt) (DrawablePtr pDrawable,
+                          GCPtr pGC,
+                          int x,
+                          int y,
+                          unsigned int nglyph,
+                          CharInfoPtr *ppci,
+                          void *pglyphBase);
 
     void (*PushPixels) (GCPtr /*pGC */ ,
                         PixmapPtr /*pBitMap */ ,
diff --git a/include/input.h b/include/input.h
index cbf949b..1b2102f 100644
--- a/include/input.h
+++ b/include/input.h
@@ -314,10 +314,10 @@ extern _X_EXPORT Bool InitTouchClassDeviceStruct(DeviceIntPtr /*device */ ,
                                                  unsigned int /*mode */ ,
                                                  unsigned int /*numAxes */ );
 
-typedef void (*BellProcPtr) (int /*percent */ ,
-                             DeviceIntPtr /*device */ ,
-                             void */*ctrl */ ,
-                             int);
+typedef void (*BellProcPtr) (int percent,
+                             DeviceIntPtr device,
+                             void *ctrl,
+                             int feedbackClass);
 
 typedef void (*KbdCtrlProcPtr) (DeviceIntPtr /*device */ ,
                                 KeybdCtrl * /*ctrl */ );
diff --git a/include/os.h b/include/os.h
index d26e399..0cbb928 100644
--- a/include/os.h
+++ b/include/os.h
@@ -139,8 +139,8 @@ extern _X_EXPORT const char *ClientAuthorized(ClientPtr /*client */ ,
                                               unsigned int /*string_n */ ,
                                               char * /*auth_string */ );
 
-extern _X_EXPORT Bool EstablishNewConnections(ClientPtr /*clientUnused */ ,
-                                              void */*closure */ );
+extern _X_EXPORT Bool EstablishNewConnections(ClientPtr clientUnused,
+                                              void *closure);
 
 extern _X_EXPORT void CheckConnections(void);
 
@@ -173,14 +173,14 @@ extern _X_EXPORT Bool AddClientOnOpenFD(int /* fd */ );
 extern _X_EXPORT CARD32 GetTimeInMillis(void);
 extern _X_EXPORT CARD64 GetTimeInMicros(void);
 
-extern _X_EXPORT void AdjustWaitForDelay(void */*waitTime */ ,
-                                         unsigned long /*newdelay */ );
+extern _X_EXPORT void AdjustWaitForDelay(void *waitTime,
+                                         unsigned long newdelay);
 
 typedef struct _OsTimerRec *OsTimerPtr;
 
-typedef CARD32 (*OsTimerCallback) (OsTimerPtr /* timer */ ,
-                                   CARD32 /* time */ ,
-                                   void */* arg */ );
+typedef CARD32 (*OsTimerCallback) (OsTimerPtr timer,
+                                   CARD32 time,
+                                   void *arg);
 
 extern _X_EXPORT void TimerInit(void);
 
@@ -189,11 +189,11 @@ extern _X_EXPORT Bool TimerForce(OsTimerPtr /* timer */ );
 #define TimerAbsolute (1<<0)
 #define TimerForceOld (1<<1)
 
-extern _X_EXPORT OsTimerPtr TimerSet(OsTimerPtr /* timer */ ,
-                                     int /* flags */ ,
-                                     CARD32 /* millis */ ,
-                                     OsTimerCallback /* func */ ,
-                                     void */* arg */ );
+extern _X_EXPORT OsTimerPtr TimerSet(OsTimerPtr timer,
+                                     int flags,
+                                     CARD32 millis,
+                                     OsTimerCallback func,
+                                     void *arg);
 
 extern _X_EXPORT void TimerCheck(void);
 extern _X_EXPORT void TimerCancel(OsTimerPtr /* pTimer */ );
@@ -210,9 +210,9 @@ extern _X_EXPORT void UseMsg(void);
 
 extern _X_EXPORT void ProcessCommandLine(int /*argc */ , char * /*argv */ []);
 
-extern _X_EXPORT int set_font_authorizations(char ** /* authorizations */ ,
-                                             int * /*authlen */ ,
-                                             void */* client */ );
+extern _X_EXPORT int set_font_authorizations(char **authorizations,
+                                             int *authlen,
+                                             void *client);
 
 #ifndef _HAVE_XALLOC_DECLS
 #define _HAVE_XALLOC_DECLS
@@ -391,18 +391,18 @@ AddHost(ClientPtr /*client */ ,
         const void * /*pAddr */ );
 
 extern _X_EXPORT Bool
-ForEachHostInFamily(int /*family */ ,
-                    Bool (* /*func */ )(
-                                           unsigned char * /* addr */ ,
-                                           short /* len */ ,
-                                           void */* closure */ ),
-                    void */*closure */ );
+ForEachHostInFamily(int family,
+                    Bool (*func)(
+                                           unsigned char *addr,
+                                           short len,
+                                           void *closure),
+                    void *closure);
 
 extern _X_EXPORT int
-RemoveHost(ClientPtr /*client */ ,
-           int /*family */ ,
-           unsigned /*length */ ,
-           void */*pAddr */ );
+RemoveHost(ClientPtr client,
+           int family,
+           unsigned length,
+           void *pAddr);
 
 extern _X_EXPORT int
 GetHosts(void ** /*data */ ,
@@ -464,7 +464,7 @@ DefineSelf(int /*fd */ );
 
 #if XDMCP
 extern _X_EXPORT void
-AugmentSelf(void */*from */ , int /*len */ );
+AugmentSelf(void *from, int len);
 
 extern _X_EXPORT void
 RegisterAuthorizations(void);
diff --git a/include/pixmap.h b/include/pixmap.h
index 46ec3f5..f3c2c60 100644
--- a/include/pixmap.h
+++ b/include/pixmap.h
@@ -93,13 +93,13 @@ typedef union _PixUnion {
 #define WindowDrawable(type) \
 	((type == DRAWABLE_WINDOW) || (type == UNDRAWABLE_WINDOW))
 
-extern _X_EXPORT PixmapPtr GetScratchPixmapHeader(ScreenPtr /*pScreen */ ,
-                                                  int /*width */ ,
-                                                  int /*height */ ,
-                                                  int /*depth */ ,
-                                                  int /*bitsPerPixel */ ,
-                                                  int /*devKind */ ,
-                                                  void */*pPixData */ );
+extern _X_EXPORT PixmapPtr GetScratchPixmapHeader(ScreenPtr pScreen,
+                                                  int width,
+                                                  int height,
+                                                  int depth,
+                                                  int bitsPerPixel,
+                                                  int devKind,
+                                                  void *pPixData);
 
 extern _X_EXPORT void FreeScratchPixmapHeader(PixmapPtr /*pPixmap */ );
 
diff --git a/include/property.h b/include/property.h
index 3b8ea8b..cae4471 100644
--- a/include/property.h
+++ b/include/property.h
@@ -57,24 +57,24 @@ extern _X_EXPORT int dixLookupProperty(PropertyPtr * /*result */ ,
                                        ClientPtr /*pClient */ ,
                                        Mask /*access_mode */ );
 
-extern _X_EXPORT int dixChangeWindowProperty(ClientPtr /*pClient */ ,
-                                             WindowPtr /*pWin */ ,
-                                             Atom /*property */ ,
-                                             Atom /*type */ ,
-                                             int /*format */ ,
-                                             int /*mode */ ,
-                                             unsigned long /*len */ ,
-                                             void */*value */ ,
-                                             Bool /*sendevent */ );
-
-extern _X_EXPORT int ChangeWindowProperty(WindowPtr /*pWin */ ,
-                                          Atom /*property */ ,
-                                          Atom /*type */ ,
-                                          int /*format */ ,
-                                          int /*mode */ ,
-                                          unsigned long /*len */ ,
-                                          void */*value */ ,
-                                          Bool /*sendevent */ );
+extern _X_EXPORT int dixChangeWindowProperty(ClientPtr pClient,
+                                             WindowPtr pWin,
+                                             Atom property,
+                                             Atom type,
+                                             int format,
+                                             int mode,
+                                             unsigned long len,
+                                             void *value,
+                                             Bool sendevent);
+
+extern _X_EXPORT int ChangeWindowProperty(WindowPtr pWin,
+                                          Atom property,
+                                          Atom type,
+                                          int format,
+                                          int mode,
+                                          unsigned long len,
+                                          void *value,
+                                          Bool sendevent);
 
 extern _X_EXPORT int DeleteProperty(ClientPtr /*client */ ,
                                     WindowPtr /*pWin */ ,
diff --git a/include/resource.h b/include/resource.h
index db44aef..fe56bb2 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -136,21 +136,21 @@ typedef struct {
     void *value;
 } ResourceStateInfoRec;
 
-typedef int (*DeleteType) (void */*value */ ,
-                           XID /*id */ );
+typedef int (*DeleteType) (void *value,
+                           XID id);
 
-typedef void (*FindResType) (void */*value */ ,
-                             XID /*id */ ,
-                             void */*cdata */ );
+typedef void (*FindResType) (void *value,
+                             XID id,
+                             void *cdata);
 
-typedef void (*FindAllRes) (void */*value */ ,
-                            XID /*id */ ,
-                            RESTYPE /*type */ ,
-                            void */*cdata */ );
+typedef void (*FindAllRes) (void *value,
+                            XID id,
+                            RESTYPE type,
+                            void *cdata);
 
-typedef Bool (*FindComplexResType) (void */*value */ ,
-                                    XID /*id */ ,
-                                    void */*cdata */ );
+typedef Bool (*FindComplexResType) (void *value,
+                                    XID id,
+                                    void *cdata);
 
 /* Structure for estimating resource memory usage. Memory usage
  * consists of space allocated for the resource itself and of
@@ -166,16 +166,16 @@ typedef struct {
     unsigned long refCnt;
 } ResourceSizeRec, *ResourceSizePtr;
 
-typedef void (*SizeType)(void */*value*/,
-                         XID /*id*/,
-                         ResourceSizePtr /*size*/);
+typedef void (*SizeType)(void *value,
+                         XID id,
+                         ResourceSizePtr size);
 
-extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType /*deleteFunc */ ,
-                                               const char * /*name */ );
+extern _X_EXPORT RESTYPE CreateNewResourceType(DeleteType deleteFunc,
+                                               const char *name);
 
-typedef void (*FindTypeSubResources)(void */* value */,
-                                     FindAllRes /* func */,
-                                     void */* cdata */);
+typedef void (*FindTypeSubResources)(void *value,
+                                     FindAllRes func,
+                                     void *cdata);
 
 extern _X_EXPORT SizeType GetResourceTypeSizeFunc(
     RESTYPE /*type*/);
@@ -200,9 +200,9 @@ extern _X_EXPORT XID FakeClientID(int /*client */ );
 #ifdef __APPLE__
 #define AddResource Darwin_X_AddResource
 #endif
-extern _X_EXPORT Bool AddResource(XID /*id */ ,
-                                  RESTYPE /*type */ ,
-                                  void */*value */ );
+extern _X_EXPORT Bool AddResource(XID id,
+                                  RESTYPE type,
+                                  void *value);
 
 extern _X_EXPORT void FreeResource(XID /*id */ ,
                                    RESTYPE /*skipDeleteFuncType */ );
@@ -211,27 +211,27 @@ extern _X_EXPORT void FreeResourceByType(XID /*id */ ,
                                          RESTYPE /*type */ ,
                                          Bool /*skipFree */ );
 
-extern _X_EXPORT Bool ChangeResourceValue(XID /*id */ ,
-                                          RESTYPE /*rtype */ ,
-                                          void */*value */ );
+extern _X_EXPORT Bool ChangeResourceValue(XID id,
+                                          RESTYPE rtype,
+                                          void *value);
 
-extern _X_EXPORT void FindClientResourcesByType(ClientPtr /*client */ ,
-                                                RESTYPE /*type */ ,
-                                                FindResType /*func */ ,
-                                                void */*cdata */ );
+extern _X_EXPORT void FindClientResourcesByType(ClientPtr client,
+                                                RESTYPE type,
+                                                FindResType func,
+                                                void *cdata);
 
-extern _X_EXPORT void FindAllClientResources(ClientPtr /*client */ ,
-                                             FindAllRes /*func */ ,
-                                             void */*cdata */ );
+extern _X_EXPORT void FindAllClientResources(ClientPtr client,
+                                             FindAllRes func,
+                                             void *cdata);
 
 /** @brief Iterate through all subresources of a resource.
 
     @note The XID argument provided to the FindAllRes function
           may be 0 for subresources that don't have an XID */
-extern _X_EXPORT void FindSubResources(void */*resource*/,
-                                       RESTYPE /*type*/,
-                                       FindAllRes /*func*/,
-                                       void */*cdata*/);
+extern _X_EXPORT void FindSubResources(void *resource,
+                                       RESTYPE type,
+                                       FindAllRes func,
+                                       void *cdata);
 
 extern _X_EXPORT void FreeClientNeverRetainResources(ClientPtr /*client */ );
 
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 6acdadd..5312781 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -259,23 +259,23 @@ typedef void (*SendGraphicsExposeProcPtr) (ClientPtr /*client */ ,
                                            int /*major */ ,
                                            int /*minor */ );
 
-typedef void (*ScreenBlockHandlerProcPtr) (ScreenPtr /*pScreen*/ ,
-                                           void */*pTimeout */ ,
-                                           void */*pReadmask */ );
+typedef void (*ScreenBlockHandlerProcPtr) (ScreenPtr pScreen,
+                                           void *pTimeout,
+                                           void *pReadmask);
 
-typedef void (*ScreenWakeupHandlerProcPtr) (ScreenPtr /*pScreen*/ ,
-                                            unsigned long /*result */ ,
-                                            void */*pReadMask */ );
+typedef void (*ScreenWakeupHandlerProcPtr) (ScreenPtr pScreen,
+                                            unsigned long result,
+                                            void *pReadMask);
 
 typedef Bool (*CreateScreenResourcesProcPtr) (ScreenPtr /*pScreen */ );
 
-typedef Bool (*ModifyPixmapHeaderProcPtr) (PixmapPtr /*pPixmap */ ,
-                                           int /*width */ ,
-                                           int /*height */ ,
-                                           int /*depth */ ,
-                                           int /*bitsPerPixel */ ,
-                                           int /*devKind */ ,
-                                           void */*pPixData */ );
+typedef Bool (*ModifyPixmapHeaderProcPtr) (PixmapPtr pPixmap,
+                                           int width,
+                                           int height,
+                                           int depth,
+                                           int bitsPerPixel,
+                                           int devKind,
+                                           void *pPixData);
 
 typedef PixmapPtr (*GetWindowPixmapProcPtr) (WindowPtr /*pWin */ );
 
diff --git a/include/window.h b/include/window.h
index b5a937e..c123728 100644
--- a/include/window.h
+++ b/include/window.h
@@ -72,16 +72,16 @@ struct _Cursor;
 typedef struct _BackingStore *BackingStorePtr;
 typedef struct _Window *WindowPtr;
 
-typedef int (*VisitWindowProcPtr) (WindowPtr /*pWin */ ,
-                                   void */*data */ );
+typedef int (*VisitWindowProcPtr) (WindowPtr pWin,
+                                   void *data);
 
-extern _X_EXPORT int TraverseTree(WindowPtr /*pWin */ ,
-                                  VisitWindowProcPtr /*func */ ,
-                                  void */*data */ );
+extern _X_EXPORT int TraverseTree(WindowPtr pWin,
+                                  VisitWindowProcPtr func,
+                                  void *data);
 
-extern _X_EXPORT int WalkTree(ScreenPtr /*pScreen */ ,
-                              VisitWindowProcPtr /*func */ ,
-                              void */*data */ );
+extern _X_EXPORT int WalkTree(ScreenPtr pScreen,
+                              VisitWindowProcPtr func,
+                              void *data);
 
 extern _X_EXPORT Bool CreateRootWindow(ScreenPtr /*pScreen */ );
 
@@ -108,8 +108,8 @@ extern _X_EXPORT WindowPtr CreateWindow(Window /*wid */ ,
                                         VisualID /*visual */ ,
                                         int * /*error */ );
 
-extern _X_EXPORT int DeleteWindow(void */*pWin */ ,
-                                  XID /*wid */ );
+extern _X_EXPORT int DeleteWindow(void *pWin,
+                                  XID wid);
 
 extern _X_EXPORT int DestroySubwindows(WindowPtr /*pWin */ ,
                                        ClientPtr /*client */ );
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 229de21..a4878fc 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -596,15 +596,15 @@ extern _X_EXPORT void XkbSendCompatMapNotify(DeviceIntPtr /* kbd */ ,
                                              xkbCompatMapNotify *       /* ev */
     );
 
-extern _X_EXPORT void XkbHandleBell(BOOL /* force */ ,
-                                    BOOL /* eventOnly */ ,
-                                    DeviceIntPtr /* kbd */ ,
-                                    CARD8 /* percent */ ,
-                                    void */* ctrl */ ,
-                                    CARD8 /* class */ ,
-                                    Atom /* name */ ,
-                                    WindowPtr /* pWin */ ,
-                                    ClientPtr   /* pClient */
+extern _X_EXPORT void XkbHandleBell(BOOL force,
+                                    BOOL eventOnly,
+                                    DeviceIntPtr kbd,
+                                    CARD8 percent,
+                                    void *ctrl,
+                                    CARD8 class,
+                                    Atom name,
+                                    WindowPtr pWin,
+                                    ClientPtr pClient
     );
 
 extern _X_EXPORT void XkbSendAccessXNotify(DeviceIntPtr /* kbd */ ,
diff --git a/mi/mi.h b/mi/mi.h
index 1209a16..483fa3e 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -265,22 +265,22 @@ extern _X_EXPORT void miPolyFillRect(DrawablePtr /*pDrawable */ ,
 
 /* miglblt.c */
 
-extern _X_EXPORT void miPolyGlyphBlt(DrawablePtr /*pDrawable */ ,
-                                     GCPtr /*pGC */ ,
-                                     int /*x */ ,
-                                     int /*y */ ,
-                                     unsigned int /*nglyph */ ,
-                                     CharInfoPtr * /*ppci */ ,
-                                     void */*pglyphBase */
+extern _X_EXPORT void miPolyGlyphBlt(DrawablePtr pDrawable,
+                                     GCPtr pGC,
+                                     int x,
+                                     int y,
+                                     unsigned int nglyph,
+                                     CharInfoPtr *ppci,
+                                     void *pglyphBase
     );
 
-extern _X_EXPORT void miImageGlyphBlt(DrawablePtr /*pDrawable */ ,
-                                      GCPtr /*pGC */ ,
-                                      int /*x */ ,
-                                      int /*y */ ,
-                                      unsigned int /*nglyph */ ,
-                                      CharInfoPtr * /*ppci */ ,
-                                      void */*pglyphBase */
+extern _X_EXPORT void miImageGlyphBlt(DrawablePtr pDrawable,
+                                      GCPtr pGC,
+                                      int x,
+                                      int y,
+                                      unsigned int nglyph,
+                                      CharInfoPtr *ppci,
+                                      void *pglyphBase
     );
 
 /* mipoly.c */
@@ -381,36 +381,36 @@ extern _X_EXPORT void miPushPixels(GCPtr /*pGC */ ,
 
 /* miscrinit.c */
 
-extern _X_EXPORT Bool miModifyPixmapHeader(PixmapPtr /*pPixmap */ ,
-                                           int /*width */ ,
-                                           int /*height */ ,
-                                           int /*depth */ ,
-                                           int /*bitsPerPixel */ ,
-                                           int /*devKind */ ,
-                                           void */*pPixData */
+extern _X_EXPORT Bool miModifyPixmapHeader(PixmapPtr pPixmap,
+                                           int width,
+                                           int height,
+                                           int depth,
+                                           int bitsPerPixel,
+                                           int devKind,
+                                           void *pPixData
     );
 
 extern _X_EXPORT Bool miCreateScreenResources(ScreenPtr /*pScreen */
     );
 
-extern _X_EXPORT Bool miScreenDevPrivateInit(ScreenPtr /*pScreen */ ,
-                                             int /*width */ ,
-                                             void */*pbits */
-    );
-
-extern _X_EXPORT Bool miScreenInit(ScreenPtr /*pScreen */ ,
-                                   void */*pbits */ ,
-                                   int /*xsize */ ,
-                                   int /*ysize */ ,
-                                   int /*dpix */ ,
-                                   int /*dpiy */ ,
-                                   int /*width */ ,
-                                   int /*rootDepth */ ,
-                                   int /*numDepths */ ,
-                                   DepthPtr /*depths */ ,
-                                   VisualID /*rootVisual */ ,
-                                   int /*numVisuals */ ,
-                                   VisualPtr    /*visuals */
+extern _X_EXPORT Bool miScreenDevPrivateInit(ScreenPtr pScreen,
+                                             int width,
+                                             void *pbits
+    );
+
+extern _X_EXPORT Bool miScreenInit(ScreenPtr pScreen,
+                                   void *pbits,
+                                   int xsize,
+                                   int ysize,
+                                   int dpix,
+                                   int dpiy,
+                                   int width,
+                                   int rootDepth,
+                                   int numDepths,
+                                   DepthPtr depths,
+                                   VisualID rootVisual,
+                                   int numVisuals,
+                                   VisualPtr visuals
     );
 
 /* mivaltree.c */
diff --git a/os/access.c b/os/access.c
index e8c0781..9fcf99a 100644
--- a/os/access.c
+++ b/os/access.c
@@ -1217,9 +1217,9 @@ AddHost(ClientPtr client, int family, unsigned length,  /* of bytes in pAddr */
 }
 
 Bool
-ForEachHostInFamily(int family, Bool (*func) (unsigned char * /* addr */ ,
-                                              short /* len */ ,
-                                              void */* closure */ ),
+ForEachHostInFamily(int family, Bool (*func) (unsigned char *addr,
+                                              short len,
+                                              void *closure),
                     void *closure)
 {
     HOST *host;
commit 8b36e1ec8dd9f53e9f4e10422c2100844e9e549c
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jul 17 00:03:33 2014 -0700

    Update to version 1.16.0
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index c214638..1c327fd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.15.99.904, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2014-07-07"
-RELEASE_NAME="Netarts Bay Oysters"
+AC_INIT([xorg-server], 1.16.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2014-07-16"
+RELEASE_NAME="Marionberry Pie"
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
commit 4dbb641bb2d4037f107b58b31e80963dc8b72c0e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jul 14 14:01:47 2014 +0200

    config_odev_add_attribute*: Check for right attribute type
    
    Don't allow setting string attributes to integers and vice versa.
    
    Signed-off-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/config/config.c b/config/config.c
index 5514516..a26d835 100644
--- a/config/config.c
+++ b/config/config.c
@@ -172,12 +172,38 @@ config_odev_find_or_add_attribute(struct OdevAttributes *attribs, int attrib)
     return oa;
 }
 
+static int config_odev_get_attribute_type(int attrib)
+{
+    switch (attrib) {
+    case ODEV_ATTRIB_PATH:
+    case ODEV_ATTRIB_SYSPATH:
+    case ODEV_ATTRIB_BUSID:
+        return ODEV_ATTRIB_STRING;
+    case ODEV_ATTRIB_FD:
+    case ODEV_ATTRIB_MAJOR:
+    case ODEV_ATTRIB_MINOR:
+        return ODEV_ATTRIB_INT;
+    case ODEV_ATTRIB_DRIVER:
+        return ODEV_ATTRIB_STRING;
+    default:
+        LogMessage(X_ERROR, "Error %s called for unknown attribute %d\n",
+                   __func__, attrib);
+        return ODEV_ATTRIB_UNKNOWN;
+    }
+}
+
 Bool
 config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
                           const char *attrib_name)
 {
     struct OdevAttribute *oa;
 
+    if (config_odev_get_attribute_type(attrib) != ODEV_ATTRIB_STRING) {
+        LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
+                   __func__, attrib);
+        return FALSE;
+    }
+
     oa = config_odev_find_or_add_attribute(attribs, attrib);
     free(oa->attrib_name);
     oa->attrib_name = XNFstrdup(attrib_name);
@@ -191,6 +217,12 @@ config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
 {
     struct OdevAttribute *oa;
 
+    if (config_odev_get_attribute_type(attrib) != ODEV_ATTRIB_INT) {
+        LogMessage(X_ERROR, "Error %s called for non integer attrib %d\n",
+                   __func__, attrib);
+        return FALSE;
+    }
+
     oa = config_odev_find_or_add_attribute(attribs, attrib);
     oa->attrib_value = attrib_value;
     oa->attrib_type = ODEV_ATTRIB_INT;
diff --git a/include/hotplug.h b/include/hotplug.h
index b2c0d78..4c2fa97 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -32,7 +32,7 @@ extern _X_EXPORT void config_pre_init(void);
 extern _X_EXPORT void config_init(void);
 extern _X_EXPORT void config_fini(void);
 
-enum { ODEV_ATTRIB_STRING, ODEV_ATTRIB_INT };
+enum { ODEV_ATTRIB_UNKNOWN = -1, ODEV_ATTRIB_STRING = 0, ODEV_ATTRIB_INT };
 
 struct OdevAttribute {
     struct xorg_list member;
commit 25eca7ce35973577c8d85704c270f7fb53e6732e
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Mon Jul 14 14:01:46 2014 +0200

    Fix ODEV_ATTRIB_DRIVER overlapping with ODEV_ATTRIB_FD
    
    Looks like the value of ODEV_ATTRIB_DRIVER was not updated when the patch
    adding it got rebased on top of a newer server version.
    
    This fixes the xserver crashing when systemd-logind integration is used.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1118540
    
    Signed-off-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/include/hotplug.h b/include/hotplug.h
index c4268a0..b2c0d78 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -88,7 +88,7 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
 /* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
 #define ODEV_ATTRIB_MINOR 6
 /* kernel driver name */
-#define ODEV_ATTRIB_DRIVER 4
+#define ODEV_ATTRIB_DRIVER 7
 
 typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
 void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
commit 9a19bf06b5b409fa0d5b5932e29cd4c5545052c5
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 14 15:05:58 2014 +1000

    Revert "dix: fix up coordinate scaling when external monitors are present"
    
    This reverts commit d90b5f83010248be65b2039b0b2d0b9e6a4e93cf.
    
    Reverting for two reasons:
    * the scaling does not work on devices that don't advertise resolution, and
      the default resolution used (100 units/mm) is higher than most devices,
      resulting in a significant slowdown of the touchpads.
    * the scaling is still affected by resolution changing. The patch worked
      before acceleration but since it maps into resolution-dependent dx/dy
      coordinates the acceleration may distort the movement after the fact. So the
      same input data generates different movements depending on the resolution.
      This can't easily be fixed for all affected devices as synaptics has its own
      velocity calculation method whereas wacom doesn't. So anything in the server
      won't work for both at the same time.
    
    Revert this for now, until a more integrated solution can be implemented.

diff --git a/dix/getevents.c b/dix/getevents.c
index d68fa96..ffa89fa 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -770,65 +770,27 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl
 }
 
 
-/* FIXME: relative events from devices with absolute axis ranges is
-   fundamentally broken. We map the device coordinate range into the screen
-   range, but don't really account for device resolution in that.
-
-   what we do here is a hack to make touchpads usable. for a given relative
-   motion vector in device coordinates:
-   1. calculate physical movement on the device in metres
-   2. calculate pixel vector that is the same physical movement on the
-      screen (times some magic number to provide sensible base speed)
-   3. calculate what percentage this vector is of the current screen
-      width/height
-   4. calculate equivalent vector in % on the device's min/max axis range
-   5. Use that device vector as the actual motion vector
-
-   e.g. 10/50mm on the device, 10/50mm on the screen are 30/100 pixels,
-   30/100 pixels are 1/3% of the width, 1/3% of the device is a vector of
-   20/80 -> use 20/80 as dx/dy.
-
-   dx/dy is then applied to the current position in device coordinates,
-   mapped to screen coordinates and thus the movement on the screen reflects
-   the motion direction on the device.
- */
 static void
 scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask)
 {
-    double x, y;
+    double y;
     ValuatorClassPtr v = dev->valuator;
     int xrange = v->axes[0].max_value - v->axes[0].min_value + 1;
     int yrange = v->axes[1].max_value - v->axes[1].min_value + 1;
 
-    /* Assume 100 units/m for devices without resolution */
-    int xres = 100000, yres = 100000;
-
-    /* If we have multiple screens with different dpi, it gets complicated:
-       we have to map which screen we're on and then take the dpi of that
-       screen to be somewhat accurate.  */
-    const ScreenPtr s = screenInfo.screens[0];
-    const double screen_res = 1000.0 * s->width/s->mmWidth; /* units/m */
+    double screen_ratio = 1.0 * screenInfo.width/screenInfo.height;
+    double device_ratio = 1.0 * xrange/yrange;
+    double resolution_ratio = 1.0;
+    double ratio;
 
-    /* some magic multiplier, so unaccelerated movement of x mm on the
-       device reflects x * magic mm on the screen */
-    const double magic = 4;
+    if (!valuator_mask_fetch_double(mask, 1, &y))
+        return;
 
-    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0) {
-        xres = v->axes[0].resolution;
-        yres = v->axes[1].resolution;
-    }
+    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0)
+        resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution;
 
-    if (valuator_mask_isset(mask, 0)) {
-        x = valuator_mask_get_double(mask, 0);
-        x = magic * x/xres * screen_res/screenInfo.width * xrange;
-        valuator_mask_set_double(mask, 0, x);
-    }
-
-    if (valuator_mask_isset(mask, 1)) {
-        y = valuator_mask_get_double(mask, 1);
-        y = magic * y/yres * screen_res/screenInfo.height * yrange;
-        valuator_mask_set_double(mask, 1, y);
-    }
+    ratio = device_ratio/resolution_ratio/screen_ratio;
+    valuator_mask_set_double(mask, 1, y / ratio);
 }
 
 /**
@@ -842,6 +804,15 @@ moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
 {
     int i;
     Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
+    ValuatorClassPtr v = dev->valuator;
+
+    /* for abs devices in relative mode, we've just scaled wrong, since we
+       mapped the device's shape into the screen shape. Undo this. */
+    if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 &&
+        v->axes[0].min_value < v->axes[0].max_value &&
+        v->axes[1].min_value < v->axes[1].max_value) {
+        scale_for_device_resolution(dev, mask);
+    }
 
     /* calc other axes, clip, drop back into valuators */
     for (i = 0; i < valuator_mask_size(mask); i++) {
@@ -1470,21 +1441,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
             set_raw_valuators(raw, &mask, raw->valuators.data);
     }
     else {
-        ValuatorClassPtr v = pDev->valuator;
-
         transformRelative(pDev, &mask);
 
-        /* for abs devices in relative mode, we've just scaled wrong, since we
-           mapped the device's shape into the screen shape. Undo this. */
-        if (v && v->numAxes > 1 &&
-            v->axes[0].min_value < v->axes[0].max_value &&
-            v->axes[1].min_value < v->axes[1].max_value) {
-            scale_for_device_resolution(pDev, &mask);
-        }
-
         if (flags & POINTER_ACCELERATE)
             accelPointer(pDev, &mask, ms);
-
         if ((flags & POINTER_NORAW) == 0 && raw)
             set_raw_valuators(raw, &mask, raw->valuators.data);
 
commit acc0b5edd1dc560b5c39dc44872b46581ec23903
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jul 11 15:56:35 2014 -0700

    xfree86: Only support one sysconfigdir
    
    When the X server is compiled with --prefix set to something other than /usr,
    then it ends up with a nonstandard sysconfigdir in its .pc file.  This causes
    various other components to install their xorg.conf.d snippets there.
    
    However, the X server first looks for /usr/share/X11/xorg.conf.d before looking
    in sysconfigdir.  That means that if the system administrator installed anything
    that created that path, the user's custom sysconfigdir is not searched.
    
    Rather than doing that, just look in the configured sysconfdir and nowhere else.
    
    Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
    Reviewed-by: Julien Cristau <jcristau at debian.org>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    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 481674d..779ba6f 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -103,7 +103,7 @@
 					"/etc/X11/%X," "%C/X11/%X"
 #endif
 #ifndef SYS_CONFIGDIRPATH
-#define SYS_CONFIGDIRPATH	"/usr/share/X11/%X," "%D/X11/%X"
+#define SYS_CONFIGDIRPATH	"%D/X11/%X"
 #endif
 #ifndef PROJECTROOT
 #define PROJECTROOT	"/usr/X11R6"
commit 578b9283bcc129d0a35fabe2637c7622085ef1e8
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jul 10 10:39:50 2014 +1000

    xfree86: don't force the screensaver off on DPMS unblank, merely suggest it
    
    Commit 41d4beb2616ceb3f1a1b8694733e85bae70de59a added symmetry to the
    screensaver/DPMS invocations so that one (en|dis)ables the other. Having
    dependencies between DPMS and the screensaver is subject to further arguments,
    but in this particular case using SCREENSAVER_FORCER is detrimental.
    SCREENSAVER_FORCER(ScreenSaverReset) resets the idle time for all
    devices on DPMS unblank.
    
    It prevents at least one use-case that GNOME tries to implement:
    GNOME displays a notification before suspending. If the display is
    currently blanked, GNOME lights it up to display the message. With the
    original patch in place DPMS unblank also resets the device idle times, thus
    restarting the timeout ad infinitum.
    
    Switch this to a more suggestive SCREENSAVER_OFF(ScreenSaverReset). This keeps
    the symmetry in blanking mode (DPMS and screensaver turn each other on/off as
    expected) but does not reset the idle time on the devices.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=731241
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>
    Reviewed-By: Egbert Eich <eich at freedesktop.org>

diff --git a/hw/xfree86/common/xf86DPMS.c b/hw/xfree86/common/xf86DPMS.c
index 14d1f45..2b5a3ed 100644
--- a/hw/xfree86/common/xf86DPMS.c
+++ b/hw/xfree86/common/xf86DPMS.c
@@ -166,7 +166,7 @@ DPMSSet(ClientPtr client, int level)
                 return rc;
         }
     } else if (!xf86IsUnblank(screenIsSaved)) {
-        rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverReset);
+        rc = dixSaveScreens(client, SCREEN_SAVER_OFF, ScreenSaverReset);
         if (rc != Success)
             return rc;
     }
commit daa1a9d22db8e83d1933d8403acf72626199ee2a
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jul 7 08:27:44 2014 +1000

    os: prevent negative array index access (#80890)
    
    If an empty string is provided to LogMessageVerbSigSafe, the length of the
    printed string is 0.
    
    Read-only access only and the only effect it had was adding a linebreak or not.
    
    X.Org Bug 80890 <http://bugs.freedesktop.org/show_bug.cgi?id=80890>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/os/log.c b/os/log.c
index a368569..2a721b9 100644
--- a/os/log.c
+++ b/os/log.c
@@ -697,7 +697,7 @@ LogVMessageVerbSigSafe(MessageType type, int verb, const char *format, va_list a
     if (sizeof(buf) - len == 1)
         buf[len - 1] = '\n';
 
-    newline = (buf[len - 1] == '\n');
+    newline = (len > 0 && buf[len - 1] == '\n');
     LogSWrite(verb, buf, len, newline);
 }
 
commit 9de3cc8daa4c6e877d30a0e8ccfe0cc159f1dbe3
Merge: 9308eaf a549987
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Jul 7 16:53:07 2014 -0700

    Merge remote-tracking branch 'jturney/master'

commit 9308eafb7d303739b81634ed2ee0da88554fd429
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Jul 7 16:28:26 2014 -0700

    Update to version 1.15.99.904
    
    One more RC to get the non-PCI patches tested before release
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 2daa6be..c214638 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.15.99.903, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2014-06-04"
-RELEASE_NAME="Strawberry Shortcake"
+AC_INIT([xorg-server], 1.15.99.904, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2014-07-07"
+RELEASE_NAME="Netarts Bay Oysters"
 AC_CONFIG_SRCDIR([Makefile.am])
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
commit b6cc489838dca0bcec7e9dbb4663b871e8cb7bc8
Author: Thierry Reding <treding at nvidia.com>
Date:   Thu Feb 13 21:09:49 2014 +0100

    xfree86: Make error message more readable
    
    While at it also replace a tab by four spaces for consistency.
    
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Tested-By: Aaron Plattner <aplattner at nvidia.com>
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Reviewed-by: Rob Clark <robdclark at gmail.com>
    Tested-by: Rob Clark <robdclark at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 0aaedab..d660761 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -58,8 +58,9 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 
     err = drmSetInterfaceVersion(fd, &sv);
     if (err) {
-        ErrorF("setversion 1.4 failed: %s\n", strerror(-err));
-	goto out;
+        xf86Msg(X_ERROR, "%s: failed to set DRM interface version 1.4: %s\n",
+                path, strerror(-err));
+        goto out;
     }
 
     /* for a delayed probe we've already added the device */
commit eeefecd9df88920d4dca4100a84a135f7f53dd82
Author: Thierry Reding <treding at nvidia.com>
Date:   Thu Feb 13 13:54:23 2014 +0100

    xfree86: Support driver loading via OutputClass
    
    Use the OutputClass configuration to determine what drivers to autoload
    for a given device.
    
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Tested-By: Aaron Plattner <aplattner at nvidia.com>
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Tested-by: Rob Clark <robdclark at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 672e2e5..eb1a3fb 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -47,6 +47,7 @@
 #include "xf86Bus.h"
 #include "Pci.h"
 #include "xf86platformBus.h"
+#include "xf86Config.h"
 
 #include "randrstr.h"
 int platformSlotClaimed;
@@ -199,6 +200,81 @@ xf86_check_platform_slot(const struct xf86_platform_device *pd)
     return TRUE;
 }
 
+static Bool
+MatchToken(const char *value, struct xorg_list *patterns,
+           int (*compare)(const char *, const char *))
+{
+    const xf86MatchGroup *group;
+
+    /* If there are no patterns, accept the match */
+    if (xorg_list_is_empty(patterns))
+        return TRUE;
+
+    /* If there are patterns but no attribute, reject the match */
+    if (!value)
+        return FALSE;
+
+    /*
+     * Otherwise, iterate the list of patterns ensuring each entry has a
+     * match. Each list entry is a separate Match line of the same type.
+     */
+    xorg_list_for_each_entry(group, patterns, entry) {
+        Bool match = FALSE;
+        char *const *cur;
+
+        for (cur = group->values; *cur; cur++) {
+            if ((*compare)(value, *cur) == 0) {
+                match = TRUE;
+                break;
+            }
+        }
+
+        if (!match)
+            return FALSE;
+    }
+
+    /* All the entries in the list matched the attribute */
+    return TRUE;
+}
+
+static Bool
+OutputClassMatches(const XF86ConfOutputClassPtr oclass, int index)
+{
+    char *driver = xf86_get_platform_attrib(index, ODEV_ATTRIB_DRIVER);
+
+    if (!MatchToken(driver, &oclass->match_driver, strcmp))
+        return FALSE;
+
+    return TRUE;
+}
+
+static int
+xf86OutputClassDriverList(int index, char *matches[], int nmatches)
+{
+    XF86ConfOutputClassPtr cl;
+    int i = 0;
+
+    if (nmatches == 0)
+        return 0;
+
+    for (cl = xf86configptr->conf_outputclass_lst; cl; cl = cl->list.next) {
+        if (OutputClassMatches(cl, index)) {
+            char *path = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH);
+
+            xf86Msg(X_INFO, "Applying OutputClass \"%s\" to %s\n",
+                    cl->identifier, path);
+            xf86Msg(X_NONE, "\tloading driver: %s\n", cl->driver);
+
+            matches[i++] = xstrdup(cl->driver);
+        }
+
+        if (i >= nmatches)
+            break;
+    }
+
+    return i;
+}
+
 /**
  *  @return The numbers of found devices that match with the current system
  *  drivers.
@@ -218,6 +294,8 @@ xf86PlatformMatchDriver(char *matches[], int nmatches)
             else if (!xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 0))
                 continue;
 
+            j += xf86OutputClassDriverList(i, &matches[j], nmatches - j);
+
             info = xf86_platform_devices[i].pdev;
 #ifdef __linux__
             if (info)
commit a270bb18baa6e3b45fa4a105a8d2be51ac5270bc
Author: Thierry Reding <treding at nvidia.com>
Date:   Thu Feb 13 13:42:05 2014 +0100

    xfree86: Introduce OutputClass configuration
    
    The OutputClass section provides a way to match output devices to a set
    of given attributes and configure them. For now, only matching by kernel
    driver name is supported. This can be used to determine what DDX module
    to load for non-PCI output devices. DDX modules can ship an xorg.conf.d
    snippet (e.g. in /usr/share/X11/xorg.conf.d) that looks like this:
    
    	Section "OutputClass"
    	    Identifer "NVIDIA Tegra open-source driver"
    	    MatchDriver "tegra"
    	    Driver "opentegra"
    	EndSection
    
    This will cause any device that's driven by the kernel driver named
    "tegra" to use the "opentegra" DDX module.
    
    See the OUTPUTCLASS section in xorg.conf(5) for more details.
    
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Tested-By: Aaron Plattner <aplattner at nvidia.com>
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Tested-by: Rob Clark <robdclark at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index cadd87b..bc33df1 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -171,6 +171,7 @@ The section names are:
 .BR "Extensions     " "Extension enabling"
 .BR "InputDevice    " "Input device description"
 .BR "InputClass     " "Input class description"
+.BR "OutputClass    " "Output class description"
 .BR "Device         " "Graphics device description"
 .BR "VideoAdaptor   " "Xv video adaptor description"
 .BR "Monitor        " "Monitor description"
@@ -1190,6 +1191,82 @@ entries.
 This optional entry specifies that the device should be ignored entirely,
 and not added to the server. This can be useful when the device is handled
 by another program and no X events should be generated.
+.SH "OUTPUTCLASS SECTION"
+The config file may have multiple
+.B OutputClass
+sections.
+These sections are optional and are used to provide configuration for a
+class of output devices as they are automatically added.
+An output device can match more than one
+.B OutputClass
+section.
+Each class can override settings from a previous class, so it is best to
+arrange the sections with the most generic matches first.
+.PP
+.B OutputClass
+sections have the following format:
+.PP
+.RS 4
+.nf
+.B  "Section \*qOutputClass\*q"
+.BI "    Identifier  \*q" name \*q
+.I  "    entries"
+.I  "    ..."
+.B  "EndSection"
+.fi
+.RE
+.PP
+The
+.B Identifier
+entry is required in all
+.B OutputClass
+sections.
+All other entries are optional.
+.PP
+The
+.B Identifier
+entry specifies the unique name for this output class.
+The
+.B Driver
+entry specifies the name of the driver to use for this output device.
+After all classes have been examined, the
+.RI \*q outputdriver \*q
+module from the first
+.B Driver
+entry will be enabled when using the loadable server.
+.PP
+When an output device is automatically added, its characteristics are
+checked against all
+.B OutputClass
+sections.
+Each section can contain optional entries to narrow the match of the class.
+If none of the optional entries appear, the
+.B OutputClass
+section is generic and will match any output device.
+If more than one of these entries appear, they all must match for the
+configuration to apply.
+.PP
+The following list of tokens can be matched against attributes of the device.
+An entry can be constructed to match attributes from different devices by
+separating arguments with a '|' character.
+.PP
+For example:
+.PP
+.RS 4
+.nf
+.B  "Section \*qOutputClass\*q"
+.B  "    Identifier   \*qMy Class\*q"
+.B  "    # kernel driver must be either foo or bar
+.B  "    MatchDriver \*qfoo|bar\*q
+.I  "    ..."
+.B  "EndSection"
+.fi
+.RE
+.TP 7
+.BI "MatchDriver \*q" matchdriver \*q
+Check the case-sensitive string
+.RI \*q matchdriver \*q
+against the kernel driver of the device.
 .SH "DEVICE SECTION"
 The config file may have multiple
 .B Device
diff --git a/hw/xfree86/parser/Makefile.am b/hw/xfree86/parser/Makefile.am
index 3bf62e8..4d0bb4f 100644
--- a/hw/xfree86/parser/Makefile.am
+++ b/hw/xfree86/parser/Makefile.am
@@ -14,6 +14,7 @@ INTERNAL_SOURCES= \
 	Flags.c \
 	Input.c \
 	InputClass.c \
+	OutputClass.c \
 	Layout.c \
 	Module.c \
 	Video.c \
diff --git a/hw/xfree86/parser/OutputClass.c b/hw/xfree86/parser/OutputClass.c
new file mode 100644
index 0000000..7e9a8ac
--- /dev/null
+++ b/hw/xfree86/parser/OutputClass.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014 NVIDIA Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE 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.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "os.h"
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+static
+xf86ConfigSymTabRec OutputClassTab[] = {
+    {ENDSECTION, "endsection"},
+    {IDENTIFIER, "identifier"},
+    {DRIVER, "driver"},
+    {MATCH_DRIVER, "matchdriver"},
+    {-1, ""},
+};
+
+#define CLEANUP xf86freeOutputClassList
+
+#define TOKEN_SEP "|"
+
+static void
+add_group_entry(struct xorg_list *head, char **values)
+{
+    xf86MatchGroup *group;
+
+    group = malloc(sizeof(*group));
+    if (group) {
+        group->values = values;
+        xorg_list_add(&group->entry, head);
+    }
+}
+
+XF86ConfOutputClassPtr
+xf86parseOutputClassSection(void)
+{
+    int has_ident = FALSE;
+    int token;
+
+    parsePrologue(XF86ConfOutputClassPtr, XF86ConfOutputClassRec)
+
+    /* Initialize MatchGroup lists */
+    xorg_list_init(&ptr->match_driver);
+
+    while ((token = xf86getToken(OutputClassTab)) != ENDSECTION) {
+        switch (token) {
+        case COMMENT:
+            ptr->comment = xf86addComment(ptr->comment, xf86_lex_val.str);
+            break;
+        case IDENTIFIER:
+            if (xf86getSubToken(&(ptr->comment)) != STRING)
+                Error(QUOTE_MSG, "Identifier");
+            if (has_ident == TRUE)
+                Error(MULTIPLE_MSG, "Identifier");
+            ptr->identifier = xf86_lex_val.str;
+            has_ident = TRUE;
+            break;
+        case DRIVER:
+            if (xf86getSubToken(&(ptr->comment)) != STRING)
+                Error(QUOTE_MSG, "Driver");
+            else
+                ptr->driver = xf86_lex_val.str;
+            break;
+        case MATCH_DRIVER:
+            if (xf86getSubToken(&(ptr->comment)) != STRING)
+                Error(QUOTE_MSG, "MatchDriver");
+            add_group_entry(&ptr->match_driver,
+                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
+            free(xf86_lex_val.str);
+            break;
+        case EOF_TOKEN:
+            Error(UNEXPECTED_EOF_MSG);
+            break;
+        default:
+            Error(INVALID_KEYWORD_MSG, xf86tokenString());
+            break;
+        }
+    }
+
+    if (!has_ident)
+        Error(NO_IDENT_MSG);
+
+#ifdef DEBUG
+    printf("OutputClass section parsed\n");
+#endif
+
+    return ptr;
+}
+void
+xf86printOutputClassSection(FILE * cf, XF86ConfOutputClassPtr ptr)
+{
+    const xf86MatchGroup *group;
+    char *const *cur;
+
+    while (ptr) {
+        fprintf(cf, "Section \"OutputClass\"\n");
+        if (ptr->comment)
+            fprintf(cf, "%s", ptr->comment);
+        if (ptr->identifier)
+            fprintf(cf, "\tIdentifier      \"%s\"\n", ptr->identifier);
+        if (ptr->driver)
+            fprintf(cf, "\tDriver          \"%s\"\n", ptr->driver);
+
+        xorg_list_for_each_entry(group, &ptr->match_driver, entry) {
+            fprintf(cf, "\tMatchDriver     \"");
+            for (cur = group->values; *cur; cur++)
+                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
+                        *cur);
+            fprintf(cf, "\"\n");
+        }
+
+        fprintf(cf, "EndSection\n\n");
+        ptr = ptr->list.next;
+    }
+}
+
+void
+xf86freeOutputClassList(XF86ConfOutputClassPtr ptr)
+{
+    XF86ConfOutputClassPtr prev;
+
+    while (ptr) {
+        xf86MatchGroup *group, *next;
+        char **list;
+
+        TestFree(ptr->identifier);
+        TestFree(ptr->comment);
+        TestFree(ptr->driver);
+
+        xorg_list_for_each_entry_safe(group, next, &ptr->match_driver, entry) {
+            xorg_list_del(&group->entry);
+            for (list = group->values; *list; list++)
+                free(*list);
+            free(group);
+        }
+
+        prev = ptr;
+        ptr = ptr->list.next;
+        free(prev);
+    }
+}
diff --git a/hw/xfree86/parser/configProcs.h b/hw/xfree86/parser/configProcs.h
index 60509dc..774e2a2 100644
--- a/hw/xfree86/parser/configProcs.h
+++ b/hw/xfree86/parser/configProcs.h
@@ -57,6 +57,11 @@ XF86ConfInputClassPtr xf86parseInputClassSection(void);
 void xf86printInputClassSection(FILE * f, XF86ConfInputClassPtr ptr);
 void xf86freeInputClassList(XF86ConfInputClassPtr ptr);
 
+/* OutputClass.c */
+XF86ConfOutputClassPtr xf86parseOutputClassSection(void);
+void xf86printOutputClassSection(FILE * f, XF86ConfOutputClassPtr ptr);
+void xf86freeOutputClassList(XF86ConfOutputClassPtr ptr);
+
 /* Layout.c */
 XF86ConfLayoutPtr xf86parseLayoutSection(void);
 void xf86printLayoutSection(FILE * cf, XF86ConfLayoutPtr ptr);
diff --git a/hw/xfree86/parser/read.c b/hw/xfree86/parser/read.c
index 2478b07..22f6e6a 100644
--- a/hw/xfree86/parser/read.c
+++ b/hw/xfree86/parser/read.c
@@ -165,6 +165,12 @@ xf86readConfigFile(void)
                 HANDLE_LIST(conf_inputclass_lst,
                             xf86parseInputClassSection, XF86ConfInputClassPtr);
             }
+            else if (xf86nameCompare(xf86_lex_val.str, "outputclass") == 0) {
+                free(xf86_lex_val.str);
+                xf86_lex_val.str = NULL;
+                HANDLE_LIST(conf_outputclass_lst, xf86parseOutputClassSection,
+                            XF86ConfOutputClassPtr);
+            }
             else if (xf86nameCompare(xf86_lex_val.str, "module") == 0) {
                 free(xf86_lex_val.str);
                 xf86_lex_val.str = NULL;
diff --git a/hw/xfree86/parser/write.c b/hw/xfree86/parser/write.c
index 26739b9..472b27b 100644
--- a/hw/xfree86/parser/write.c
+++ b/hw/xfree86/parser/write.c
@@ -114,6 +114,8 @@ doWriteConfigFile(const char *filename, XF86ConfigPtr cptr)
 
     xf86printInputClassSection(cf, cptr->conf_inputclass_lst);
 
+    xf86printOutputClassSection(cf, cptr->conf_outputclass_lst);
+
     xf86printVideoAdaptorSection(cf, cptr->conf_videoadaptor_lst);
 
     xf86printModesSection(cf, cptr->conf_modes_lst);
diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
index c95423a..3fa5b71 100644
--- a/hw/xfree86/parser/xf86Parser.h
+++ b/hw/xfree86/parser/xf86Parser.h
@@ -327,6 +327,14 @@ typedef struct {
     char *comment;
 } XF86ConfInputClassRec, *XF86ConfInputClassPtr;
 
+typedef struct {
+    GenericListRec list;
+    char *identifier;
+    char *driver;
+    struct xorg_list match_driver;
+    char *comment;
+} XF86ConfOutputClassRec, *XF86ConfOutputClassPtr;
+
 /* Values for adj_where */
 #define CONF_ADJ_OBSOLETE	-1
 #define CONF_ADJ_ABSOLUTE	0
@@ -411,6 +419,7 @@ typedef struct {
     XF86ConfScreenPtr conf_screen_lst;
     XF86ConfInputPtr conf_input_lst;
     XF86ConfInputClassPtr conf_inputclass_lst;
+    XF86ConfOutputClassPtr conf_outputclass_lst;
     XF86ConfLayoutPtr conf_layout_lst;
     XF86ConfVendorPtr conf_vendor_lst;
     XF86ConfDRIPtr conf_dri;
commit 856bb80cea695106a8f6767d00918b38795b51c6
Author: Thierry Reding <treding at nvidia.com>
Date:   Wed Feb 12 16:43:29 2014 +0100

    xfree86: Store kernel driver name in platform device attribute
    
    When opening a DRM device, query the version and store the driver name
    as a new attribute for future reference.
    
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Tested-By: Aaron Plattner <aplattner at nvidia.com>
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Reviewed-by: Rob Clark <robdclark at gmail.com>
    Tested-by: Rob Clark <robdclark at gmail.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c
index 308275a..0aaedab 100644
--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -24,6 +24,7 @@ static Bool
 get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
 {
     drmSetVersion sv;
+    drmVersionPtr v;
     char *buf;
     int major, minor, fd;
     int err = 0;
@@ -74,6 +75,17 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
     xf86_add_platform_device_attrib(delayed_index,
                                     ODEV_ATTRIB_BUSID, buf);
     drmFreeBusid(buf);
+
+    v = drmGetVersion(fd);
+    if (!v) {
+        xf86Msg(X_ERROR, "%s: failed to query DRM version\n", path);
+        goto out;
+    }
+
+    xf86_add_platform_device_attrib(delayed_index, ODEV_ATTRIB_DRIVER,
+                                    v->name);
+    drmFreeVersion(v);
+
 out:
     if (!server_fd)
         close(fd);
diff --git a/include/hotplug.h b/include/hotplug.h
index cefc164..c4268a0 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -87,6 +87,8 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
 #define ODEV_ATTRIB_MAJOR 5
 /* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
 #define ODEV_ATTRIB_MINOR 6
+/* kernel driver name */
+#define ODEV_ATTRIB_DRIVER 4
 
 typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
 void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
commit 5a4e15c3f6fb8d674879e54458328e9f595d9451
Author: Thierry Reding <treding at nvidia.com>
Date:   Fri Feb 14 15:45:33 2014 +0100

    xfree86: Make driver matching consistent
    
    Most of the driver enumeration functions take an array and a maximum
    number of entries that they are allowed to fill in. Upon success, they
    return the number of entries filled in. This allows them to be easily
    used to consecutively.
    
    One exception is the xf86MatchDriverFromFiles() function, which doesn't
    return a value, so callers have to manually search the array for the
    first empty entry.
    
    This commit modifies the xf86MatchDriverFromFiles() to behave the same
    way as others, which makes it easier to deal with.
    
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>
    Tested-By: Aaron Plattner <aplattner at nvidia.com>
    Tested-by: Rob Clark <robdclark at gmail.com>  (on arm / platform device)
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/common/xf86AutoConfig.c b/hw/xfree86/common/xf86AutoConfig.c
index 4eb86de..2b53b90 100644
--- a/hw/xfree86/common/xf86AutoConfig.c
+++ b/hw/xfree86/common/xf86AutoConfig.c
@@ -265,7 +265,7 @@ listPossibleVideoDrivers(char *matches[], int nmatches)
 #endif
 #ifdef XSERVER_LIBPCIACCESS
     if (i < (nmatches - 1))
-        i = xf86PciMatchDriver(matches, nmatches);
+        i += xf86PciMatchDriver(&matches[i], nmatches - i);
 #endif
 
 #if defined(__linux__)
diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
index 0f76a03..c06b040 100644
--- a/hw/xfree86/common/xf86pciBus.c
+++ b/hw/xfree86/common/xf86pciBus.c
@@ -1320,8 +1320,9 @@ xchomp(char *line)
  * don't export their PCI ID's properly. If distros don't end up using this
  * feature it can and should be removed because the symbol-based resolution
  * scheme should be the primary one */
-void
-xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_chip)
+int
+xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip,
+                         char *matches[], int nmatches)
 {
     DIR *idsdir;
     FILE *fp;
@@ -1331,11 +1332,11 @@ xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_c
     ssize_t read;
     char path_name[256], vendor_str[5], chip_str[5];
     uint16_t vendor, chip;
-    int i, j;
+    int i = 0, j;
 
     idsdir = opendir(PCI_TXT_IDS_PATH);
     if (!idsdir)
-        return;
+        return 0;
 
     xf86Msg(X_INFO,
             "Scanning %s directory for additional PCI ID's supported by the drivers\n",
@@ -1386,10 +1387,6 @@ xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_c
                         }
                     }
                     if (vendor == match_vendor && chip == match_chip) {
-                        i = 0;
-                        while (matches[i]) {
-                            i++;
-                        }
                         matches[i] =
                             (char *) malloc(sizeof(char) *
                                             strlen(direntry->d_name) - 3);
@@ -1412,6 +1409,7 @@ xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_c
                         }
                         xf86Msg(X_INFO, "Matched %s from file name %s\n",
                                 matches[i], direntry->d_name);
+                        i++;
                     }
                 }
                 else {
@@ -1425,6 +1423,7 @@ xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_c
  end:
     free(line);
     closedir(idsdir);
+    return i;
 }
 #endif                          /* __linux__ */
 
@@ -1435,7 +1434,7 @@ xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_c
 int
 xf86PciMatchDriver(char *matches[], int nmatches)
 {
-    int i;
+    int i = 0;
     struct pci_device *info = NULL;
     struct pci_device_iterator *iter;
 
@@ -1450,13 +1449,10 @@ xf86PciMatchDriver(char *matches[], int nmatches)
     pci_iterator_destroy(iter);
 #ifdef __linux__
     if (info)
-        xf86MatchDriverFromFiles(matches, info->vendor_id, info->device_id);
+        i += xf86MatchDriverFromFiles(info->vendor_id, info->device_id,
+                                      matches, nmatches);
 #endif
 
-    for (i = 0; (i < nmatches) && (matches[i]); i++) {
-        /* find end of matches list */
-    }
-
     if ((info != NULL) && (i < nmatches)) {
         i += xf86VideoPtrToDriverList(info, &(matches[i]), nmatches - i);
     }
diff --git a/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h
index b497a7f..45b5a0f 100644
--- a/hw/xfree86/common/xf86pciBus.h
+++ b/hw/xfree86/common/xf86pciBus.h
@@ -47,8 +47,9 @@ void xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo,
                                  ((x)->func == (y)->func) &&            \
                                  ((x)->dev == (y)->dev))
 
-void
-xf86MatchDriverFromFiles(char **matches, uint16_t match_vendor, uint16_t match_chip);
+int
+xf86MatchDriverFromFiles(uint16_t match_vendor, uint16_t match_chip,
+                         char *matches[], int nmatches);
 int
 xf86VideoPtrToDriverList(struct pci_device *dev,
                          char *returnList[], int returnListMax);
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index dd118a2..672e2e5 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -221,13 +221,10 @@ xf86PlatformMatchDriver(char *matches[], int nmatches)
             info = xf86_platform_devices[i].pdev;
 #ifdef __linux__
             if (info)
-                xf86MatchDriverFromFiles(matches, info->vendor_id, info->device_id);
+                j += xf86MatchDriverFromFiles(info->vendor_id, info->device_id,
+                                              &matches[j], nmatches - j);
 #endif
 
-            for (j = 0; (j < nmatches) && (matches[j]); j++) {
-                /* find end of matches list */
-            }
-
             if ((info != NULL) && (j < nmatches)) {
                 j += xf86VideoPtrToDriverList(info, &(matches[j]), nmatches - j);
             }
commit a61ca6f006d70343c88fe45206fae0669d1e8971
Author: Tomasz Borowik <timon37 at gmail.com>
Date:   Thu Jul 3 13:04:44 2014 -0700

    glamor: Fix stack corruption in glamor_init
    
    glGet on GL_MAX_VIEWPORT_DIMS returns two values
    
    Reviewed-by: Markus Wick <markus at selfnet.de>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index c398807..3588903 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -316,7 +316,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 {
     glamor_screen_private *glamor_priv;
     int gl_version;
-    int max_viewport_size;
+    int max_viewport_size[2];
 
 #ifdef RENDER
     PictureScreenPtr ps = GetPictureScreenIfSet(screen);
@@ -408,8 +408,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     glamor_priv->has_buffer_storage =
         epoxy_has_gl_extension("GL_ARB_buffer_storage");
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &max_viewport_size);
-    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
+    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]);
+    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]);
 #ifdef MAX_FBO_SIZE
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
 #endif
commit 10d2805dbc6b96a159b8c5acedcd53f34df362bf
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Jun 26 14:12:24 2014 -0700

    fb: Don't free NULL pixmap in fbCloseScreen. Bug #80313
    
    We fixed fbCloseScreen to use the FreePixmap function so that the
    private counts would be updated correctly during CloseScreen. Xvfb
    calls FreePixmap and sets devPrivate to NULL before fbCloseScreen is
    called; not checking devPrivate before calling would result in a NULL
    pointer dereference.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Julien Cristau <jcristau at debian.org>

diff --git a/fb/fbscreen.c b/fb/fbscreen.c
index 1f91089..0d4d87f 100644
--- a/fb/fbscreen.c
+++ b/fb/fbscreen.c
@@ -37,7 +37,8 @@ fbCloseScreen(ScreenPtr pScreen)
         free(depths[d].vids);
     free(depths);
     free(pScreen->visuals);
-    FreePixmap((PixmapPtr)pScreen->devPrivate);
+    if (pScreen->devPrivate)
+        FreePixmap((PixmapPtr)pScreen->devPrivate);
     return TRUE;
 }
 
commit a5499870e2f88822f52b1b54cad0db69856597c0
Author: Yaakov Selkowitz <yselkowitz at users.sourceforge.net>
Date:   Sun Apr 6 04:47:15 2014 -0500

    hw/xwin: link dynamically and export symbols
    
    With my patch to fix shared libXfont to work correctly on Cygwin/Win32,
    there is no need for -static anymore.  But, XWin.exe must export its
    symbols in order for them to override libXfont's stubs.
    
    Signed-off-by: Yaakov Selkowitz <yselkowitz at users.sourceforge.net>
    Reviewed-by: Jon TURNEY <jon.turney at dronecode.org.uk>

diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index cf42cfd..4ee9632 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -155,7 +155,7 @@ XWIN_LIBS += 	$(top_builddir)/pseudoramiX/libPseudoramiX.la \
                 $(top_builddir)/Xi/libXistubs.la
 XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS)
 XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS)
-XWin_LDFLAGS = -mwindows -static -Wl,--disable-stdcall-fixup
+XWin_LDFLAGS = -mwindows -Wl,--disable-stdcall-fixup $(LD_EXPORT_SYMBOLS_FLAG)
 
 
 .rc.o:
commit a3b44ad8db1fa2f3b81c1ff9498f31c5323edd37
Author: Thierry Reding <treding at nvidia.com>
Date:   Wed Jun 25 16:03:29 2014 +0200

    exa: Fix a warning when enabling DEBUG_TRACE_FALL
    
    The format string wants a picture and a character, but the argument list
    contains only a character, causing GCC to complain. Add the missing
    argument.
    
    Signed-off-by: Thierry Reding <treding at nvidia.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index 58262e0..b0c6344 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -685,7 +685,7 @@ ExaCheckAddTraps(PicturePtr pPicture,
 
     EXA_PRE_FALLBACK(pScreen);
 
-    EXA_FALLBACK(("to pict %p (%c)\n",
+    EXA_FALLBACK(("to pict %p (%c)\n", pPicture,
                   exaDrawableLocation(pPicture->pDrawable)));
     exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
     swap(pExaScr, ps, AddTraps);
commit 2f113d68f6c1572576bc57ecca12e44cc9e438eb
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Mon Jun 16 11:34:55 2014 -0700

    xwayland: Add glamor and DRI3 support
    
    Reviewed-by: Axel Davy <axel.davy at ens.fr>
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index dabebb9..2daa6be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -810,7 +810,7 @@ LIBDMX="dmx >= 1.0.99.1"
 LIBDRI="dri >= 7.8.0"
 LIBDRM="libdrm >= 2.3.0"
 LIBEGL="egl"
-LIBGBM="gbm >= 9"
+LIBGBM="gbm >= 10.2.0"
 LIBGL="gl >= 7.1.0"
 LIBXEXT="xext >= 1.0.99.4"
 LIBXFONT="xfont >= 1.4.2"
@@ -2459,6 +2459,10 @@ if test "x$XWAYLAND" = xyes; then
 	XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XWAYLAND_LIBS])
 	AC_SUBST([XWAYLAND_SYS_LIBS])
+
+	WAYLAND_PREFIX=`$PKG_CONFIG --variable=prefix wayland-client`
+	AC_PATH_PROG([WAYLAND_SCANNER], [wayland-scanner],,
+		     [${WAYLAND_PREFIX}/bin$PATH_SEPARATOR$PATH])
 fi
 
 
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 36e6127..dc16b8b 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -1,10 +1,13 @@
 bin_PROGRAMS = Xwayland
 
 Xwayland_CFLAGS =				\
+	-I$(top_srcdir)/glamor			\
 	-I$(top_srcdir)/dri3			\
 	-DHAVE_DIX_CONFIG_H			\
 	$(XWAYLANDMODULES_CFLAGS)		\
-	$(DIX_CFLAGS)
+	$(DIX_CFLAGS)				\
+	$(GLAMOR_CFLAGS)			\
+	$(GBM_CFLAGS)
 
 Xwayland_SOURCES =				\
 	xwayland.c				\
@@ -19,6 +22,7 @@ Xwayland_SOURCES =				\
 	$(top_srcdir)/mi/miinitext.c
 
 Xwayland_LDADD =				\
+	$(glamor_lib)				\
 	$(XWAYLAND_LIBS)			\
 	$(XWAYLAND_SYS_LIBS)			\
 	$(XSERVER_SYS_LIBS)
@@ -26,5 +30,30 @@ Xwayland_DEPENDENCIES = $(XWAYLAND_LIBS)
 Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 
 
+if GLAMOR_EGL
+Xwayland_SOURCES += xwayland-glamor.c
+
+nodist_Xwayland_SOURCES =			\
+	drm-client-protocol.h			\
+	drm-protocol.c
+
+CLEANFILES = $(nodist_Xwayland_SOURCES)
+
+EXTRA_DIST = drm.xml
+
+xwayland-glamor.c : $(nodist_Xwayland_SOURCES)
+
+glamor_lib = $(top_builddir)/glamor/libglamor.la
+
+Xwayland_LDADD += $(GLAMOR_LIBS) $(GBM_LIBS) -lEGL -lGL
+endif
+
+
 relink:
 	$(AM_V_at)rm -f Xwayland$(EXEEXT) && $(MAKE) Xwayland$(EXEEXT)
+
+%-protocol.c : %.xml
+	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
+
+%-client-protocol.h : %.xml
+	$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
diff --git a/hw/xwayland/drm.xml b/hw/xwayland/drm.xml
new file mode 100644
index 0000000..8a3ad69
--- /dev/null
+++ b/hw/xwayland/drm.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="drm">
+
+  <copyright>
+    Copyright © 2008-2011 Kristian Høgsberg
+    Copyright © 2010-2011 Intel Corporation
+
+    Permission to use, copy, modify, distribute, and sell this
+    software and its documentation for any purpose is hereby granted
+    without fee, provided that\n 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.
+  </copyright>
+
+  <!-- drm support. This object is created by the server and published
+       using the display's global event. -->
+  <interface name="wl_drm" version="2">
+    <enum name="error">
+      <entry name="authenticate_fail" value="0"/>
+      <entry name="invalid_format" value="1"/>
+      <entry name="invalid_name" value="2"/>
+    </enum>
+
+    <enum name="format">
+      <!-- The drm format codes match the #defines in drm_fourcc.h.
+           The formats actually supported by the compositor will be
+           reported by the format event. -->
+      <entry name="c8" value="0x20203843"/>
+      <entry name="rgb332" value="0x38424752"/>
+      <entry name="bgr233" value="0x38524742"/>
+      <entry name="xrgb4444" value="0x32315258"/>
+      <entry name="xbgr4444" value="0x32314258"/>
+      <entry name="rgbx4444" value="0x32315852"/>
+      <entry name="bgrx4444" value="0x32315842"/>
+      <entry name="argb4444" value="0x32315241"/>
+      <entry name="abgr4444" value="0x32314241"/>
+      <entry name="rgba4444" value="0x32314152"/>
+      <entry name="bgra4444" value="0x32314142"/>
+      <entry name="xrgb1555" value="0x35315258"/>
+      <entry name="xbgr1555" value="0x35314258"/>
+      <entry name="rgbx5551" value="0x35315852"/>
+      <entry name="bgrx5551" value="0x35315842"/>
+      <entry name="argb1555" value="0x35315241"/>
+      <entry name="abgr1555" value="0x35314241"/>
+      <entry name="rgba5551" value="0x35314152"/>
+      <entry name="bgra5551" value="0x35314142"/>
+      <entry name="rgb565" value="0x36314752"/>
+      <entry name="bgr565" value="0x36314742"/>
+      <entry name="rgb888" value="0x34324752"/>
+      <entry name="bgr888" value="0x34324742"/>
+      <entry name="xrgb8888" value="0x34325258"/>
+      <entry name="xbgr8888" value="0x34324258"/>
+      <entry name="rgbx8888" value="0x34325852"/>
+      <entry name="bgrx8888" value="0x34325842"/>
+      <entry name="argb8888" value="0x34325241"/>
+      <entry name="abgr8888" value="0x34324241"/>
+      <entry name="rgba8888" value="0x34324152"/>
+      <entry name="bgra8888" value="0x34324142"/>
+      <entry name="xrgb2101010" value="0x30335258"/>
+      <entry name="xbgr2101010" value="0x30334258"/>
+      <entry name="rgbx1010102" value="0x30335852"/>
+      <entry name="bgrx1010102" value="0x30335842"/>
+      <entry name="argb2101010" value="0x30335241"/>
+      <entry name="abgr2101010" value="0x30334241"/>
+      <entry name="rgba1010102" value="0x30334152"/>
+      <entry name="bgra1010102" value="0x30334142"/>
+      <entry name="yuyv" value="0x56595559"/>
+      <entry name="yvyu" value="0x55595659"/>
+      <entry name="uyvy" value="0x59565955"/>
+      <entry name="vyuy" value="0x59555956"/>
+      <entry name="ayuv" value="0x56555941"/>
+      <entry name="nv12" value="0x3231564e"/>
+      <entry name="nv21" value="0x3132564e"/>
+      <entry name="nv16" value="0x3631564e"/>
+      <entry name="nv61" value="0x3136564e"/>
+      <entry name="yuv410" value="0x39565559"/>
+      <entry name="yvu410" value="0x39555659"/>
+      <entry name="yuv411" value="0x31315559"/>
+      <entry name="yvu411" value="0x31315659"/>
+      <entry name="yuv420" value="0x32315559"/>
+      <entry name="yvu420" value="0x32315659"/>
+      <entry name="yuv422" value="0x36315559"/>
+      <entry name="yvu422" value="0x36315659"/>
+      <entry name="yuv444" value="0x34325559"/>
+      <entry name="yvu444" value="0x34325659"/>
+    </enum>
+
+    <!-- Call this request with the magic received from drmGetMagic().
+         It will be passed on to the drmAuthMagic() or
+         DRIAuthConnection() call.  This authentication must be
+         completed before create_buffer could be used. -->
+    <request name="authenticate">
+      <arg name="id" type="uint"/>
+    </request>
+
+    <!-- Create a wayland buffer for the named DRM buffer.  The DRM
+         surface must have a name using the flink ioctl -->
+    <request name="create_buffer">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="stride" type="uint"/>
+      <arg name="format" type="uint"/>
+    </request>
+
+    <!-- Create a wayland buffer for the named DRM buffer.  The DRM
+         surface must have a name using the flink ioctl -->
+    <request name="create_planar_buffer">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="format" type="uint"/>
+      <arg name="offset0" type="int"/>
+      <arg name="stride0" type="int"/>
+      <arg name="offset1" type="int"/>
+      <arg name="stride1" type="int"/>
+      <arg name="offset2" type="int"/>
+      <arg name="stride2" type="int"/>
+    </request>
+
+    <!-- Create a wayland buffer for the prime fd.  Use for regular and planar
+         buffers.  Pass 0 for offset and stride for unused planes. -->
+    <request name="create_prime_buffer" since="2">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="fd"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="format" type="uint"/>
+      <arg name="offset0" type="int"/>
+      <arg name="stride0" type="int"/>
+      <arg name="offset1" type="int"/>
+      <arg name="stride1" type="int"/>
+      <arg name="offset2" type="int"/>
+      <arg name="stride2" type="int"/>
+    </request>
+
+    <!-- Notification of the path of the drm device which is used by
+         the server.  The client should use this device for creating
+         local buffers.  Only buffers created from this device should
+         be be passed to the server using this drm object's
+         create_buffer request. -->
+    <event name="device">
+      <arg name="name" type="string"/>
+    </event>
+
+    <event name="format">
+      <arg name="format" type="uint"/>
+    </event>
+
+    <!-- Raised if the authenticate request succeeded -->
+    <event name="authenticated"/>
+
+    <enum name="capability" since="2">
+      <description summary="wl_drm capability bitmask">
+        Bitmask of capabilities.
+      </description>
+      <entry name="prime" value="1" summary="wl_drm prime available"/>
+    </enum>
+
+    <event name="capabilities">
+      <arg name="value" type="uint"/>
+    </event>
+  </interface>
+
+</protocol>
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
new file mode 100644
index 0000000..4be883f
--- /dev/null
+++ b/hw/xwayland/xwayland-glamor.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of the
+ * copyright holders not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "xwayland.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <xf86drm.h>
+
+#define MESA_EGL_NO_X11_HEADERS
+#include <gbm.h>
+#include <epoxy/egl.h>
+#include <epoxy/gl.h>
+
+#include <glamor.h>
+#include <glamor_context.h>
+#include <dri3.h>
+#include "drm-client-protocol.h"
+
+struct xwl_pixmap {
+    struct wl_buffer *buffer;
+    struct gbm_bo *bo;
+    void *image;
+    unsigned int texture;
+};
+
+static void
+xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
+{
+    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");
+}
+
+static uint32_t
+drm_format_for_depth(int depth)
+{
+    switch (depth) {
+    case 15:
+        return WL_DRM_FORMAT_XRGB1555;
+    case 16:
+        return WL_DRM_FORMAT_RGB565;
+    case 24:
+        return WL_DRM_FORMAT_XRGB8888;
+    default:
+        ErrorF("unexpected depth: %d\n", depth);
+    case 32:
+        return WL_DRM_FORMAT_ARGB8888;
+    }
+}
+
+static uint32_t
+gbm_format_for_depth(int depth)
+{
+    switch (depth) {
+    case 16:
+        return GBM_FORMAT_RGB565;
+    case 24:
+        return GBM_FORMAT_XRGB8888;
+    default:
+        ErrorF("unexpected depth: %d\n", depth);
+    case 32:
+        return GBM_FORMAT_ARGB8888;
+    }
+}
+
+void
+glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+
+    glamor_ctx->ctx = xwl_screen->egl_context;
+    glamor_ctx->display = xwl_screen->egl_display;
+
+    glamor_ctx->make_current = xwl_glamor_egl_make_current;
+
+    xwl_screen->glamor_ctx = glamor_ctx;
+}
+
+static PixmapPtr
+xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
+{
+    PixmapPtr pixmap;
+    struct xwl_pixmap *xwl_pixmap;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+
+    xwl_pixmap = malloc(sizeof *xwl_pixmap);
+    if (xwl_pixmap == NULL)
+        return NULL;
+
+    pixmap = glamor_create_pixmap(screen,
+                                  gbm_bo_get_width(bo),
+                                  gbm_bo_get_height(bo),
+                                  depth,
+                                  GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
+    if (pixmap == NULL) {
+        free(xwl_pixmap);
+        return NULL;
+    }
+
+    if (lastGLContext != xwl_screen->glamor_ctx) {
+        lastGLContext = xwl_screen->glamor_ctx;
+        xwl_glamor_egl_make_current(xwl_screen->glamor_ctx);
+    }
+
+    xwl_pixmap->bo = bo;
+    xwl_pixmap->buffer = NULL;
+    xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
+                                          xwl_screen->egl_context,
+                                          EGL_NATIVE_PIXMAP_KHR,
+                                          xwl_pixmap->bo, NULL);
+
+    glGenTextures(1, &xwl_pixmap->texture);
+    glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+    glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
+    glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+
+    return pixmap;
+}
+
+struct wl_buffer *
+xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    int prime_fd;
+
+    if (xwl_pixmap->buffer)
+        return xwl_pixmap->buffer;
+
+    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
+    if (prime_fd == -1)
+        return NULL;
+
+    xwl_pixmap->buffer =
+        wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
+                                   pixmap->drawable.width,
+                                   pixmap->drawable.height,
+                                   drm_format_for_depth(pixmap->drawable.depth),
+                                   0, gbm_bo_get_stride(xwl_pixmap->bo),
+                                   0, 0,
+                                   0, 0);
+
+    close(prime_fd);
+
+    return xwl_pixmap->buffer;
+}
+
+static PixmapPtr
+xwl_glamor_create_pixmap(ScreenPtr screen,
+                         int width, int height, int depth, unsigned int hint)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct gbm_bo *bo;
+
+    if (width > 0 && height > 0 && depth >= 15 &&
+        (hint == 0 ||
+         hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
+         hint == CREATE_PIXMAP_USAGE_SHARED)) {
+        bo = gbm_bo_create(xwl_screen->gbm, width, height,
+                           gbm_format_for_depth(depth),
+                           GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+
+        if (bo)
+            return xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
+    }
+
+    return glamor_create_pixmap(screen, width, height, depth, hint);
+}
+
+static Bool
+xwl_glamor_destroy_pixmap(PixmapPtr pixmap)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+    if (xwl_pixmap && pixmap->refcnt == 1) {
+        if (xwl_pixmap->buffer)
+            wl_buffer_destroy(xwl_pixmap->buffer);
+
+        eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
+        gbm_bo_destroy(xwl_pixmap->bo);
+        free(xwl_pixmap);
+    }
+
+    return glamor_destroy_pixmap(pixmap);
+}
+
+static Bool
+xwl_glamor_create_screen_resources(ScreenPtr screen)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    int ret;
+
+    screen->CreateScreenResources = xwl_screen->CreateScreenResources;
+    ret = (*screen->CreateScreenResources) (screen);
+    xwl_screen->CreateScreenResources = screen->CreateScreenResources;
+    screen->CreateScreenResources = xwl_glamor_create_screen_resources;
+
+    if (!ret)
+        return ret;
+
+    if (xwl_screen->rootless)
+        screen->devPrivate =
+            fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
+    else {
+        screen->devPrivate =
+            xwl_glamor_create_pixmap(screen, screen->width, screen->height,
+                                     screen->rootDepth,
+                                     CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
+        if (screen->devPrivate)
+            glamor_set_screen_pixmap(screen->devPrivate, NULL);
+    }
+
+    return screen->devPrivate != NULL;
+}
+
+static char
+is_fd_render_node(int fd)
+{
+    struct stat render;
+
+    if (fstat(fd, &render))
+        return 0;
+    if (!S_ISCHR(render.st_mode))
+        return 0;
+    if (render.st_rdev & 0x80)
+        return 1;
+
+    return 0;
+}
+
+static void
+xwl_drm_init_egl(struct xwl_screen *xwl_screen)
+{
+    EGLint major, minor;
+    const char *version;
+
+    if (xwl_screen->egl_display)
+        return;
+
+    xwl_screen->expecting_event--;
+
+    xwl_screen->gbm = gbm_create_device(xwl_screen->drm_fd);
+    if (xwl_screen->gbm == NULL) {
+        ErrorF("couldn't get display device\n");
+        return;
+    }
+
+    xwl_screen->egl_display = eglGetDisplay(xwl_screen->gbm);
+    if (xwl_screen->egl_display == EGL_NO_DISPLAY) {
+        ErrorF("eglGetDisplay() failed\n");
+        return;
+    }
+
+    eglBindAPI(EGL_OPENGL_API);
+    if (!eglInitialize(xwl_screen->egl_display, &major, &minor)) {
+        ErrorF("eglInitialize() failed\n");
+        return;
+    }
+
+    version = eglQueryString(xwl_screen->egl_display, EGL_VERSION);
+    ErrorF("glamor: EGL version %s:\n", version);
+
+    xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
+                                               NULL, EGL_NO_CONTEXT, NULL);
+    if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
+        ErrorF("Failed to create EGL context\n");
+        return;
+    }
+
+    if (!eglMakeCurrent(xwl_screen->egl_display,
+                        EGL_NO_SURFACE, EGL_NO_SURFACE,
+                        xwl_screen->egl_context)) {
+        ErrorF("Failed to make EGL context current\n");
+        return;
+    }
+
+    if (!epoxy_has_gl_extension("GL_OES_EGL_image")) {
+        ErrorF("GL_OES_EGL_image no available");
+        return;
+    }
+
+    return;
+}
+
+static void
+xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
+{
+   struct xwl_screen *xwl_screen = data;
+   drm_magic_t magic;
+
+   xwl_screen->device_name = strdup(device);
+   if (!xwl_screen->device_name)
+      return;
+
+   xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
+   if (xwl_screen->drm_fd == -1) {
+       ErrorF("wayland-egl: could not open %s (%s)",
+	      xwl_screen->device_name, strerror(errno));
+       return;
+   }
+
+   if (is_fd_render_node(xwl_screen->drm_fd)) {
+       xwl_screen->fd_render_node = 1;
+       xwl_drm_init_egl(xwl_screen);
+   } else {
+       drmGetMagic(xwl_screen->drm_fd, &magic);
+       wl_drm_authenticate(xwl_screen->drm, magic);
+   }
+}
+
+static void
+xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
+{
+   struct xwl_screen *xwl_screen = data;
+
+   switch (format) {
+   case WL_DRM_FORMAT_ARGB8888:
+      xwl_screen->formats |= XWL_FORMAT_ARGB8888;
+      break;
+   case WL_DRM_FORMAT_XRGB8888:
+      xwl_screen->formats |= XWL_FORMAT_XRGB8888;
+      break;
+   case WL_DRM_FORMAT_RGB565:
+      xwl_screen->formats |= XWL_FORMAT_RGB565;
+      break;
+   }
+}
+
+static void
+xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    if (!xwl_screen->egl_display)
+        xwl_drm_init_egl(xwl_screen);
+}
+
+static void
+xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
+{
+   struct xwl_screen *xwl_screen = data;
+
+   xwl_screen->capabilities = value;
+}
+
+static const struct wl_drm_listener xwl_drm_listener = {
+    xwl_drm_handle_device,
+    xwl_drm_handle_format,
+    xwl_drm_handle_authenticated,
+    xwl_drm_handle_capabilities
+};
+
+Bool
+xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
+                       uint32_t id, uint32_t version)
+{
+    if (version < 2)
+        return FALSE;
+
+    xwl_screen->drm =
+        wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2);
+    wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
+    xwl_screen->expecting_event++;
+
+    return TRUE;
+}
+
+void
+glamor_egl_destroy_textured_pixmap(PixmapPtr pixmap)
+{
+    glamor_destroy_textured_pixmap(pixmap);
+}
+
+int
+glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
+                                 PixmapPtr pixmap,
+                                 unsigned int tex,
+                                 Bool want_name, CARD16 *stride, CARD32 *size)
+{
+    return 0;
+}
+
+unsigned int
+glamor_egl_create_argb8888_based_texture(ScreenPtr screen, int w, int h)
+{
+    return 0;
+}
+
+struct xwl_auth_state {
+    int fd;
+    ClientPtr client;
+};
+
+static void
+sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
+{
+    struct xwl_auth_state *state = data;
+
+    dri3_send_open_reply(state->client, state->fd);
+    AttendClient(state->client);
+    free(state);
+    wl_callback_destroy(callback);
+}
+
+static const struct wl_callback_listener sync_listener = {
+   sync_callback
+};
+
+static int
+xwl_dri3_open_client(ClientPtr client,
+                     ScreenPtr screen,
+                     RRProviderPtr provider,
+                     int *pfd)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_auth_state *state;
+    struct wl_callback *callback;
+    drm_magic_t magic;
+    int fd;
+
+    fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
+    if (fd < 0)
+        return BadAlloc;
+    if (xwl_screen->fd_render_node) {
+        *pfd = fd;
+        return Success;
+    }
+
+    state = malloc(sizeof *state);
+    if (state == NULL) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    state->client = client;
+    state->fd = fd;
+
+    if (drmGetMagic(state->fd, &magic) < 0) {
+        close(state->fd);
+        free(state);
+        return BadMatch;
+    }
+
+    wl_drm_authenticate(xwl_screen->drm, magic);
+    callback = wl_display_sync(xwl_screen->display);
+    wl_callback_add_listener(callback, &sync_listener, state);
+
+    IgnoreClient(client);
+
+    return Success;
+}
+
+static PixmapPtr
+xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
+                        CARD16 width, CARD16 height, CARD16 stride,
+                        CARD8 depth, CARD8 bpp)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct gbm_import_fd_data data;
+    struct gbm_bo *bo;
+    PixmapPtr pixmap;
+
+    if (width == 0 || height == 0 ||
+        depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
+        return NULL;
+
+    data.fd = fd;
+    data.width = width;
+    data.height = height;
+    data.stride = stride;
+    data.format = gbm_format_for_depth(depth);
+    bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD, &data,
+                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+    if (bo == NULL)
+        return NULL;
+
+    pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
+    if (pixmap == NULL) {
+        gbm_bo_destroy(bo);
+        return NULL;
+    }
+
+    return pixmap;
+}
+
+static int
+xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
+                        CARD16 *stride, CARD32 *size)
+{
+    struct xwl_pixmap *xwl_pixmap;
+
+    xwl_pixmap = xwl_pixmap_get(pixmap);
+
+    *stride = gbm_bo_get_stride(xwl_pixmap->bo);
+    *size = pixmap->drawable.width * *stride;
+
+    return gbm_bo_get_fd(xwl_pixmap->bo);
+}
+
+static dri3_screen_info_rec xwl_dri3_info = {
+    .version = 1,
+    .open = NULL,
+    .pixmap_from_fd = xwl_dri3_pixmap_from_fd,
+    .fd_from_pixmap = xwl_dri3_fd_from_pixmap,
+    .open_client = xwl_dri3_open_client,
+};
+
+Bool
+xwl_glamor_init(struct xwl_screen *xwl_screen)
+{
+    ScreenPtr screen = xwl_screen->screen;
+
+    if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
+        ErrorF("Disabling glamor and dri3, EGL setup failed\n");
+        return FALSE;
+    }
+
+    if (!glamor_init(xwl_screen->screen,
+                     GLAMOR_INVERTED_Y_AXIS |
+                     GLAMOR_USE_EGL_SCREEN |
+                     GLAMOR_USE_SCREEN |
+                     GLAMOR_USE_PICTURE_SCREEN)) {
+        ErrorF("Failed to initialize glamor\n");
+        return FALSE;
+    }
+
+    if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
+        ErrorF("Failed to initialize dri3\n");
+        return FALSE;
+    }
+
+    xwl_screen->CreateScreenResources = screen->CreateScreenResources;
+    screen->CreateScreenResources = xwl_glamor_create_screen_resources;
+    screen->CreatePixmap = xwl_glamor_create_pixmap;
+    screen->DestroyPixmap = xwl_glamor_destroy_pixmap;
+
+    return TRUE;
+}
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index b966e50..17b7bf7 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -337,7 +337,13 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)
 
         pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
 
-        buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+#if GLAMOR_HAS_GBM
+        if (xwl_screen->glamor)
+            buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
+#endif
+        if (!xwl_screen->glamor)
+            buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+
         wl_surface_attach(xwl_window->surface, buffer, 0, 0);
         for (i = 0; i < count; i++) {
             box = &RegionRects(region)[i];
@@ -373,6 +379,12 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
         xwl_output_create(xwl_screen, id);
         xwl_screen->expecting_event++;
     }
+#ifdef GLAMOR_HAS_GBM
+    else if (xwl_screen->glamor &&
+             strcmp(interface, "wl_drm") == 0 && version >= 2) {
+        xwl_screen_init_glamor(xwl_screen, id, version);
+    }
+#endif
 }
 
 static void
@@ -495,6 +507,10 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
     dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
     xwl_screen->screen = pScreen;
 
+#ifdef GLAMOR_HAS_GBM
+    xwl_screen->glamor = 1;
+#endif
+
     for (i = 1; i < argc; i++) {
         if (strcmp(argv[i], "-rootless") == 0) {
             xwl_screen->rootless = 1;
@@ -514,6 +530,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
                 atoi(argv[i + 1]);
             i++;
         }
+        else if (strcmp(argv[i], "-shm") == 0) {
+            xwl_screen->glamor = 0;
+        }
     }
 
     if (xwl_screen->listen_fd_count > 0) {
@@ -591,10 +610,19 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
     if (!xwl_screen_init_cursor(xwl_screen))
         return FALSE;
 
-    xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
-    pScreen->CreatePixmap = xwl_shm_create_pixmap;
-    pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
+#ifdef GLAMOR_HAS_GBM
+    if (xwl_screen->glamor && !xwl_glamor_init(xwl_screen)) {
+        ErrorF("Failed to initialize glamor, falling back to sw\n");
+        xwl_screen->glamor = 0;
+    }
+#endif
+
+    if (!xwl_screen->glamor) {
+        xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
+        pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
+        pScreen->CreatePixmap = xwl_shm_create_pixmap;
+        pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
+    }
 
     xwl_screen->RealizeWindow = pScreen->RealizeWindow;
     pScreen->RealizeWindow = xwl_realize_window;
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 8157e71..fc68550 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -55,6 +55,7 @@ struct xwl_screen {
     int listen_fds[5];
     int listen_fd_count;
     int rootless;
+    int glamor;
 
     CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr CloseScreen;
@@ -83,6 +84,16 @@ struct xwl_screen {
 #define XWL_FORMAT_RGB565   (1 << 2)
 
     int prepare_read;
+
+    char *device_name;
+    int drm_fd;
+    int fd_render_node;
+    struct wl_drm *drm;
+    uint32_t formats;
+    uint32_t capabilities;
+    void *egl_display, *egl_context;
+    struct gbm_device *gbm;
+    struct glamor_context *glamor_ctx;
 };
 
 struct xwl_window {
@@ -161,4 +172,10 @@ Bool xwl_shm_destroy_pixmap(PixmapPtr pixmap);
 struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
 
 
+Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
+
+Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
+                         uint32_t id, uint32_t version);
+struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
+
 #endif
commit fd16555c2fc606fc43236050deba558c20e184e8
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Jun 24 16:09:19 2014 +0900

    Revert "glamor: Fix coordinates handling for composite source/mask pictures"
    
    This reverts commit 4e9aabb6fc15d8052934f20c6a07801c197ec36a.
    
    It broke kwin decorations with XRender compositing.
    
    Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 5a7a238..14ab738 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,
-                                            x_source,
-                                            y_source,
+                                            extent->x1 + x_source - x_dest,
+                                            extent->y1 + y_source - y_dest,
                                             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 = 0;
-        y_temp_src = 0;
+        x_temp_src = -extent->x1 + x_dest;
+        y_temp_src = -extent->y1 + y_dest;
     }
 
     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,
-                                            x_mask,
-                                            y_mask,
+                                            extent->x1 + x_mask - x_dest,
+                                            extent->y1 + y_mask - y_dest,
                                             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 = 0;
-        y_temp_mask = 0;
+        x_temp_mask = -extent->x1 + x_dest;
+        y_temp_mask = -extent->y1 + y_dest;
     }
     /* Do two-pass PictOpOver componentAlpha, until we enable
      * dual source color blending.
commit 18744907d0766b1b57be12df5adafd0f93221006
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 10 07:45:05 2014 +0100

    dri2: Invalidate DRI2Buffers upon SetWindowPixmap updates
    
    When transitioning to a redirected or unredirected Window, the Composite
    layer modifies the Window's Pixmap. However, the DRI2Buffer for the
    Drawable is still pointing to the backing bo of the old Pixmap with the
    result that rendering goes astray.
    
    This now also effects DRI2 Drawables that are touched by PresentPixmap.
    
    v2: Fixup the function name after rebasing
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    Cc: Reinis Danne <reinis.danne at gmail.com>
    Reviewed-by: Dave Airlie <airlied at redhat.com>
    Cc: Keith Packard <keithp at keithp.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 5705baa..6459f11 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -130,6 +130,7 @@ typedef struct _DRI2Screen {
     HandleExposuresProcPtr HandleExposures;
 
     ConfigNotifyProcPtr ConfigNotify;
+    SetWindowPixmapProcPtr SetWindowPixmap;
     DRI2CreateBuffer2ProcPtr CreateBuffer2;
     DRI2DestroyBuffer2ProcPtr DestroyBuffer2;
     DRI2CopyRegion2ProcPtr CopyRegion2;
@@ -1378,6 +1379,21 @@ DRI2ConfigNotify(WindowPtr pWin, int x, int y, int w, int h, int bw,
     return Success;
 }
 
+static void
+DRI2SetWindowPixmap(WindowPtr pWin, PixmapPtr pPix)
+{
+    DrawablePtr pDraw = (DrawablePtr) pWin;
+    ScreenPtr pScreen = pDraw->pScreen;
+    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+    pScreen->SetWindowPixmap = ds->SetWindowPixmap;
+    (*pScreen->SetWindowPixmap) (pWin, pPix);
+    ds->SetWindowPixmap = pScreen->SetWindowPixmap;
+    pScreen->SetWindowPixmap = DRI2SetWindowPixmap;
+
+    DRI2InvalidateDrawableAll(pDraw);
+}
+
 #define MAX_PRIME DRI2DriverPrimeMask
 static int
 get_prime_id(void)
@@ -1524,6 +1540,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     ds->ConfigNotify = pScreen->ConfigNotify;
     pScreen->ConfigNotify = DRI2ConfigNotify;
 
+    ds->SetWindowPixmap = pScreen->SetWindowPixmap;
+    pScreen->SetWindowPixmap = DRI2SetWindowPixmap;
+
     xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n");
     for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) {
         if (i < ds->numDrivers && ds->driverNames[i]) {
@@ -1548,6 +1567,7 @@ DRI2CloseScreen(ScreenPtr pScreen)
     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
 
     pScreen->ConfigNotify = ds->ConfigNotify;
+    pScreen->SetWindowPixmap = ds->SetWindowPixmap;
 
     if (ds->prime_id)
         prime_id_allocate_bitmask &= ~(1 << ds->prime_id);
commit 4d92fab39c4225e89f2d157a1f559cb0618a6eaa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 18 11:14:43 2014 +0100

    dri2: Use the PrimeScreen when creating/reusing buffers
    
    This fixes a segfault when we attempt to call ds->ReuseBufferNotify()
    passing a Prime DRI2BufferPtr to the master backend.
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80001
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    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 6dd7796..5705baa 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -415,18 +415,14 @@ DRI2DrawableGone(void *p, XID id)
 }
 
 static DRI2BufferPtr
-create_buffer(DrawablePtr pDraw,
+create_buffer(DRI2ScreenPtr ds, DrawablePtr pDraw,
               unsigned int attachment, unsigned int format)
 {
-    ScreenPtr primeScreen;
-    DRI2DrawablePtr pPriv;
-    DRI2ScreenPtr ds;
     DRI2BufferPtr buffer;
-    pPriv = DRI2GetDrawable(pDraw);
-    primeScreen = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
-    ds = DRI2GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
     if (ds->CreateBuffer2)
-        buffer = (*ds->CreateBuffer2)(primeScreen, pDraw, attachment, format);
+        buffer = (*ds->CreateBuffer2)(GetScreenPrime(pDraw->pScreen,
+                                                     DRI2GetDrawable(pDraw)->prime_id),
+                                      pDraw, attachment, format);
     else
         buffer = (*ds->CreateBuffer)(pDraw, attachment, format);
     return buffer;
@@ -475,7 +471,7 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
     if ((old_buf < 0)
         || attachment == DRI2BufferFrontLeft
         || !dimensions_match || (pPriv->buffers[old_buf]->format != format)) {
-        *buffer = create_buffer (pDraw, attachment, format);
+        *buffer = create_buffer(ds, pDraw, attachment, format);
         return TRUE;
 
     }
@@ -538,7 +534,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height,
         return NULL;
     }
 
-    ds = DRI2GetScreen(pDraw->pScreen);
+    ds = DRI2GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
 
     dimensions_match = (pDraw->width == pPriv->width)
         && (pDraw->height == pPriv->height);
commit 0d9ad781807022d78239327ed508758a3f88b090
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jun 16 08:06:53 2014 +0100

    glamor: Fix GLES2 non-VBO temporary memory allocation.
    
    We'd get a request for like 16 bytes, claim to have allocated
    GLAMOR_VBO_SIZE, and then not reallocate when something a request
    bigger than 16 came along.  The intent was to always allocate at least
    GLAMOR_VBO_SIZE.
    
    Fixes segfaults with Xephyr -glamor_gles2 and running gnome-terminal.
    
    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_vbo.c b/glamor/glamor_vbo.c
index c678559..e906101 100644
--- a/glamor/glamor_vbo.c
+++ b/glamor/glamor_vbo.c
@@ -119,7 +119,7 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset)
         if (glamor_priv->vbo_size < size) {
             glamor_priv->vbo_size = MAX(GLAMOR_VBO_SIZE, size);
             free(glamor_priv->vb);
-            glamor_priv->vb = XNFalloc(size);
+            glamor_priv->vb = XNFalloc(glamor_priv->vbo_size);
         }
         *vbo_offset = NULL;
         /* We point to the start of glamor_priv->vb every time, and
commit 736bed2aaf4bb672b6c7b33146fe84700baf22bd
Merge: ce581ac d90b5f8
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Jun 23 14:18:03 2014 -0700

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

commit ce581ac3fa80c4c52d87bd54fa92bc566b7d6adc
Author: Axel Davy <axel.davy at ens.fr>
Date:   Wed Jun 18 22:22:09 2014 -0400

    present: fix bad logic in cancelling scheduled operations.
    
    If we present several pixmaps in advance for different msc, the later one
    shouldn't cancel the previous ones.
    
    This reverts a change made by commit
    e6f5d9d7b7efdacea0f22f1808efca849bcede4c
    
    Without this fix, vblank_mode=0 glxgears doesn't update
    with the present fallback.
    
    Signed-off-by: Axel Davy <axel.davy at ens.fr>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/present/present.c b/present/present.c
index 271c251..3aea0d7 100644
--- a/present/present.c
+++ b/present/present.c
@@ -771,7 +771,7 @@ present_pixmap(WindowPtr window,
             if (!vblank->queued)
                 continue;
 
-            if (vblank->crtc != target_crtc || vblank->target_msc > target_msc)
+            if (vblank->crtc != target_crtc || vblank->target_msc != target_msc)
                 continue;
 
             DebugPresent(("\tx %lld %p %8lld: %08lx -> %08lx (crtc %p)\n",
commit adb7bc3386559dfee34b359dadcbb6796bc416e7
Author: Dinar Valeev <dvaleev at suse.com>
Date:   Mon Feb 24 11:36:54 2014 +0100

    arch: Fix image and bitmap byte order for ppc64le
    
    So far PPC was big endian for sure. For ppc64le this is no longer
    true.
    
    Signed-off-by: Egbert Eich <eich at freedesktop.org>
    Reviewed-by: Mark Kettenis <kettenis at openbsd.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/include/servermd.h b/include/servermd.h
index 081123b..e413314 100644
--- a/include/servermd.h
+++ b/include/servermd.h
@@ -114,8 +114,13 @@ SOFTWARE.
 
 #if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__)
 
-#define IMAGE_BYTE_ORDER        MSBFirst
-#define BITMAP_BIT_ORDER        MSBFirst
+#if defined(__LITTLE_ENDIAN__)
+#define IMAGE_BYTE_ORDER      LSBFirst
+#define BITMAP_BIT_ORDER      LSBFirst
+#else
+#define IMAGE_BYTE_ORDER      MSBFirst
+#define BITMAP_BIT_ORDER      MSBFirst
+#endif
 #define GLYPHPADBYTES           4
 
 #endif                          /* PowerPC */
commit ea47341792cf06eda5bbdf0aca48aacc024a5be0
Merge: 334faab a11bbd8
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Jun 23 13:50:54 2014 -0700

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

commit 334faabe682a422075ba214501c7554dd5ee5563
Author: Frank Binns <frank.binns at imgtec.com>
Date:   Tue Jun 10 13:43:31 2014 +0100

    present: restore screen pixmap when aborting a flip
    
    If a 2D application is started on top of a fullscreen 3D application, which
    is flipping, then we need to stop flipping and restore the root window, and
    possibly the flip window, to using the screen pixmap. Normally this would
    be done as part of an unflip. However, in the case that there is a pending
    flip there is no mechanism to abort so the unflip is deferred until the
    pending flip completes. This provides a window of opportunity for the 2D
    application to draw to the wrong pixmap.
    
    Restore the screen pixmap at the point a pending flip is marked as aborted,
    thus avoiding this issue.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Frank Binns <frank.binns at imgtec.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/present/present.c b/present/present.c
index 165860a..271c251 100644
--- a/present/present.c
+++ b/present/present.c
@@ -383,6 +383,24 @@ present_set_tree_pixmap(WindowPtr window, PixmapPtr pixmap)
 }
 
 static void
+present_set_abort_flip(ScreenPtr screen)
+{
+    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+    /* Switch back to using the screen pixmap now to avoid
+     * 2D applications drawing to the wrong pixmap.
+     */
+
+    if (screen_priv->flip_window)
+        present_set_tree_pixmap(screen_priv->flip_window,
+                                  (*screen->GetScreenPixmap)(screen));
+
+    present_set_tree_pixmap(screen->root, (*screen->GetScreenPixmap)(screen));
+
+    screen_priv->flip_pending->abort_flip = TRUE;
+}
+
+static void
 present_unflip(ScreenPtr screen)
 {
     present_screen_priv_ptr screen_priv = present_screen_priv(screen);
@@ -511,7 +529,7 @@ present_check_flip_window (WindowPtr window)
         if (flip_pending->window == window) {
             if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap,
                                     flip_pending->sync_flip, NULL, 0, 0))
-                flip_pending->abort_flip = TRUE;
+                present_set_abort_flip(screen);
         }
     } else {
         /*
@@ -634,7 +652,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
             /* Check pending flip
              */
             if (window == screen_priv->flip_pending->window)
-                screen_priv->flip_pending->abort_flip = TRUE;
+                present_set_abort_flip(screen);
         } else if (!screen_priv->unflip_event_id) {
 
             /* Check current flip
@@ -916,7 +934,7 @@ present_flip_destroy(ScreenPtr screen)
 
     /* Do the actual cleanup once the flip has been performed by the hardware */
     if (screen_priv->flip_pending)
-        screen_priv->flip_pending->abort_flip = TRUE;
+        present_set_abort_flip(screen);
 }
 
 void
commit d90b5f83010248be65b2039b0b2d0b9e6a4e93cf
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri May 30 09:56:37 2014 +1000

    dix: fix up coordinate scaling when external monitors are present
    
    The goal of all this is to get an x/y motion reflecting the motion
    on the device, i.e. a circle on the device is a circle on the screen.
    
    This is currently done by scaling the y coordinate depending on the screen
    ratio vs device ratio. Depending on that ratio the movement on the y axis may
    be accelerated (ratio < 1) or slowed (ratio > 1). This leads to the weird
    effect that changing the screen ratio by plugging a new monitor changes the
    speed of the touchpad.
    
    Use a different algorithm: calculate the physical movement on the device, map
    that to the same-ish distance on the screen, then convert that back into a
    device-specific vector. This way we get the same mapping regardless of the
    current screen dimensions.
    
    Since the pointer accel code doesn't take device resolution into account, make
    sure we apply our crazy mapping before we accelerate. This way we accelerate
    resolution-independent.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/dix/getevents.c b/dix/getevents.c
index ffa89fa..d68fa96 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -770,27 +770,65 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl
 }
 
 
+/* FIXME: relative events from devices with absolute axis ranges is
+   fundamentally broken. We map the device coordinate range into the screen
+   range, but don't really account for device resolution in that.
+
+   what we do here is a hack to make touchpads usable. for a given relative
+   motion vector in device coordinates:
+   1. calculate physical movement on the device in metres
+   2. calculate pixel vector that is the same physical movement on the
+      screen (times some magic number to provide sensible base speed)
+   3. calculate what percentage this vector is of the current screen
+      width/height
+   4. calculate equivalent vector in % on the device's min/max axis range
+   5. Use that device vector as the actual motion vector
+
+   e.g. 10/50mm on the device, 10/50mm on the screen are 30/100 pixels,
+   30/100 pixels are 1/3% of the width, 1/3% of the device is a vector of
+   20/80 -> use 20/80 as dx/dy.
+
+   dx/dy is then applied to the current position in device coordinates,
+   mapped to screen coordinates and thus the movement on the screen reflects
+   the motion direction on the device.
+ */
 static void
 scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask)
 {
-    double y;
+    double x, y;
     ValuatorClassPtr v = dev->valuator;
     int xrange = v->axes[0].max_value - v->axes[0].min_value + 1;
     int yrange = v->axes[1].max_value - v->axes[1].min_value + 1;
 
-    double screen_ratio = 1.0 * screenInfo.width/screenInfo.height;
-    double device_ratio = 1.0 * xrange/yrange;
-    double resolution_ratio = 1.0;
-    double ratio;
+    /* Assume 100 units/m for devices without resolution */
+    int xres = 100000, yres = 100000;
 
-    if (!valuator_mask_fetch_double(mask, 1, &y))
-        return;
+    /* If we have multiple screens with different dpi, it gets complicated:
+       we have to map which screen we're on and then take the dpi of that
+       screen to be somewhat accurate.  */
+    const ScreenPtr s = screenInfo.screens[0];
+    const double screen_res = 1000.0 * s->width/s->mmWidth; /* units/m */
 
-    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0)
-        resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution;
+    /* some magic multiplier, so unaccelerated movement of x mm on the
+       device reflects x * magic mm on the screen */
+    const double magic = 4;
 
-    ratio = device_ratio/resolution_ratio/screen_ratio;
-    valuator_mask_set_double(mask, 1, y / ratio);
+    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0) {
+        xres = v->axes[0].resolution;
+        yres = v->axes[1].resolution;
+    }
+
+    if (valuator_mask_isset(mask, 0)) {
+        x = valuator_mask_get_double(mask, 0);
+        x = magic * x/xres * screen_res/screenInfo.width * xrange;
+        valuator_mask_set_double(mask, 0, x);
+    }
+
+    if (valuator_mask_isset(mask, 1)) {
+        y = valuator_mask_get_double(mask, 1);
+        y = magic * y/yres * screen_res/screenInfo.height * yrange;
+        valuator_mask_set_double(mask, 1, y);
+    }
 }
 
 /**
@@ -804,15 +842,6 @@ moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
 {
     int i;
     Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
-    ValuatorClassPtr v = dev->valuator;
-
-    /* for abs devices in relative mode, we've just scaled wrong, since we
-       mapped the device's shape into the screen shape. Undo this. */
-    if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 &&
-        v->axes[0].min_value < v->axes[0].max_value &&
-        v->axes[1].min_value < v->axes[1].max_value) {
-        scale_for_device_resolution(dev, mask);
-    }
 
     /* calc other axes, clip, drop back into valuators */
     for (i = 0; i < valuator_mask_size(mask); i++) {
@@ -1441,10 +1470,21 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
             set_raw_valuators(raw, &mask, raw->valuators.data);
     }
     else {
+        ValuatorClassPtr v = pDev->valuator;
+
         transformRelative(pDev, &mask);
 
+        /* for abs devices in relative mode, we've just scaled wrong, since we
+           mapped the device's shape into the screen shape. Undo this. */
+        if (v && v->numAxes > 1 &&
+            v->axes[0].min_value < v->axes[0].max_value &&
+            v->axes[1].min_value < v->axes[1].max_value) {
+            scale_for_device_resolution(pDev, &mask);
+        }
+
         if (flags & POINTER_ACCELERATE)
             accelPointer(pDev, &mask, ms);
+
         if ((flags & POINTER_NORAW) == 0 && raw)
             set_raw_valuators(raw, &mask, raw->valuators.data);
 
commit 382ff4a306b97b0ddcdac03ce8611b026ca5323b
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jun 17 15:50:48 2014 -0700

    present: Remove executing vblank from window list. Bug# 79709.
    
    Once the vblank is actually getting executed, it's lifetime is no
    longer tied to the window, and so it shouldn't be controlled by window
    destruction. In particular, if the vblank is queued for flip, it will
    get stored in the flip_pending field, and will be correctly destroyed
    when the flip completes.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/present/present.c b/present/present.c
index 1bf3a58..165860a 100644
--- a/present/present.c
+++ b/present/present.c
@@ -578,6 +578,7 @@ present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
     }
 
     xorg_list_del(&vblank->event_queue);
+    xorg_list_del(&vblank->window_list);
     vblank->queued = FALSE;
 
     if (vblank->pixmap && vblank->window) {
commit 199d9a6a942af9b443616f6ef6d26052ef3f48b9
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 11:12:27 2013 -0800

    xephyr: Allow initializing glamor with gles2 (on GLX).
    
    This should be useful for glamor development, so you can test both
    paths (which are significantly different, and apparently
    glamor_gradient.c was broken on GLES2 as of the import).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index eaf5654..8fe7516 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -52,6 +52,7 @@
 static Display *dpy;
 static XVisualInfo *visual_info;
 static GLXFBConfig fb_config;
+Bool ephyr_glamor_gles2;
 /** @} */
 
 /**
@@ -145,6 +146,10 @@ ephyr_glamor_setup_texturing_shader(struct ephyr_glamor *glamor)
         "}\n";
 
     const char *fs_source =
+        "#ifdef GL_ES\n"
+        "precision mediump float;\n"
+        "#endif\n"
+        "\n"
         "varying vec2 t;\n"
         "uniform sampler2D s; /* initially 0 */\n"
         "\n"
@@ -276,7 +281,24 @@ ephyr_glamor_glx_screen_init(xcb_window_t win)
 
     glx_win = glXCreateWindow(dpy, fb_config, win, NULL);
 
-    ctx = glXCreateContext(dpy, visual_info, NULL, True);
+    if (ephyr_glamor_gles2) {
+        static const int context_attribs[] = {
+            GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
+            GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+            GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT,
+            0,
+        };
+        if (epoxy_has_glx_extension(dpy, DefaultScreen(dpy),
+                                    "GLX_EXT_create_context_es2_profile")) {
+            ctx = glXCreateContextAttribsARB(dpy, fb_config, NULL, True,
+                                             context_attribs);
+        } else {
+            FatalError("Xephyr -glamor_gles2 rquires "
+                       "GLX_EXT_create_context_es2_profile\n");
+        }
+    } else {
+        ctx = glXCreateContext(dpy, visual_info, NULL, True);
+    }
     if (ctx == NULL)
         FatalError("glXCreateContext failed\n");
 
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index fac84cd..17f070d 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -35,7 +35,7 @@ extern Bool EphyrWantGrayScale;
 extern Bool EphyrWantResize;
 extern Bool kdHasPointer;
 extern Bool kdHasKbd;
-extern Bool ephyr_glamor;
+extern Bool ephyr_glamor, ephyr_glamor_gles2;
 
 #ifdef GLXEXT
 extern Bool ephyrNoDRI;
@@ -138,6 +138,7 @@ ddxUseMsg(void)
     ErrorF("-resizeable          Make Xephyr windows resizeable\n");
 #ifdef GLAMOR
     ErrorF("-glamor              Enable 2D acceleration using glamor\n");
+    ErrorF("-glamor_gles2        Enable 2D acceleration using glamor (with GLES2 only)\n");
 #endif
     ErrorF
         ("-fakexa              Simulate acceleration using software rendering\n");
@@ -251,6 +252,15 @@ ddxProcessArgument(int argc, char **argv, int i)
         ephyrFuncs.finiAccel = ephyr_glamor_fini;
         return 1;
     }
+    else if (!strcmp (argv[i], "-glamor_gles2")) {
+        ephyr_glamor = TRUE;
+        ephyr_glamor_gles2 = TRUE;
+        ephyrFuncs.initAccel = ephyr_glamor_init;
+        ephyrFuncs.enableAccel = ephyr_glamor_enable;
+        ephyrFuncs.disableAccel = ephyr_glamor_disable;
+        ephyrFuncs.finiAccel = ephyr_glamor_fini;
+        return 1;
+    }
 #endif
     else if (!strcmp(argv[i], "-fakexa")) {
         ephyrFuncs.initAccel = ephyrDrawInit;
commit 98b6158bc1e32aaca375829452266e013a520e14
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Apr 6 07:44:20 2014 +0100

    glamor: Share code for put_image handling.
    
    The difference between the two is that XF86 has the clip helper that
    lets you upload less data when rendering video that's clipped.  I
    don't think that's really worth the trouble, especially in a world of
    compositors, so I've dropped it to get to shared code.
    
    It turns out the clipping code was broken on xf86-video-intel anyway.
    To reproduce, run without a compositor, and use another window to clip
    the top half of your XV output on the glamor XV adaptor: the rendering
    got confused about which half of the window was being drawn to.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index a0b1062..535d0ca 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -1068,6 +1068,18 @@ int glamor_xv_get_port_attribute(glamor_port_private *port_priv,
 int glamor_xv_query_image_attributes(int id,
                                      unsigned short *w, unsigned short *h,
                                      int *pitches, int *offsets);
+int glamor_xv_put_image(glamor_port_private *port_priv,
+                        DrawablePtr pDrawable,
+                        short src_x, short src_y,
+                        short drw_x, short drw_y,
+                        short src_w, short src_h,
+                        short drw_w, short drw_h,
+                        int id,
+                        unsigned char *buf,
+                        short width,
+                        short height,
+                        Bool sync,
+                        RegionPtr clipBoxes);
 void glamor_xv_core_init(ScreenPtr screen);
 void glamor_xv_render(glamor_port_private *port_priv);
 
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 4aaa866..1e8bdb8 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -380,6 +380,110 @@ glamor_xv_render(glamor_port_private *port_priv)
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
 
+int
+glamor_xv_put_image(glamor_port_private *port_priv,
+                    DrawablePtr pDrawable,
+                    short src_x, short src_y,
+                    short drw_x, short drw_y,
+                    short src_w, short src_h,
+                    short drw_w, short drw_h,
+                    int id,
+                    unsigned char *buf,
+                    short width,
+                    short height,
+                    Bool sync,
+                    RegionPtr clipBoxes)
+{
+    ScreenPtr pScreen = pDrawable->pScreen;
+    int srcPitch, srcPitch2;
+    int top, nlines;
+    int s2offset, s3offset, tmp;
+
+    s2offset = s3offset = srcPitch2 = 0;
+
+    srcPitch = width;
+    srcPitch2 = width >> 1;
+
+    if (!port_priv->src_pix[0] ||
+        (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
+        int i;
+
+        for (i = 0; i < 3; i++)
+            if (port_priv->src_pix[i])
+                glamor_destroy_pixmap(port_priv->src_pix[i]);
+
+        port_priv->src_pix[0] =
+            glamor_create_pixmap(pScreen, width, height, 8, 0);
+        port_priv->src_pix[1] =
+            glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
+        port_priv->src_pix[2] =
+            glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
+        port_priv->src_pix_w = width;
+        port_priv->src_pix_h = height;
+
+        if (!port_priv->src_pix[0] || !port_priv->src_pix[1] ||
+            !port_priv->src_pix[2])
+            return BadAlloc;
+    }
+
+    top = (src_y) & ~1;
+    nlines = (src_y + height) - top;
+
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+        s2offset = srcPitch * height;
+        s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
+        s2offset += ((top >> 1) * srcPitch2);
+        s3offset += ((top >> 1) * srcPitch2);
+        if (id == FOURCC_YV12) {
+            tmp = s2offset;
+            s2offset = s3offset;
+            s3offset = tmp;
+        }
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
+                                            0, 0, srcPitch, nlines,
+                                            port_priv->src_pix[0]->devKind,
+                                            buf + (top * srcPitch), 0);
+
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
+                                            0, 0, srcPitch2, (nlines + 1) >> 1,
+                                            port_priv->src_pix[1]->devKind,
+                                            buf + s2offset, 0);
+
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
+                                            0, 0, srcPitch2, (nlines + 1) >> 1,
+                                            port_priv->src_pix[2]->devKind,
+                                            buf + s3offset, 0);
+        break;
+    default:
+        return BadMatch;
+    }
+
+    if (pDrawable->type == DRAWABLE_WINDOW)
+        port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
+    else
+        port_priv->pPixmap = (PixmapPtr) pDrawable;
+
+    if (!RegionEqual(&port_priv->clip, clipBoxes)) {
+        RegionCopy(&port_priv->clip, clipBoxes);
+    }
+
+    port_priv->src_x = src_x;
+    port_priv->src_y = src_y;
+    port_priv->src_w = src_w;
+    port_priv->src_h = src_h;
+    port_priv->dst_w = drw_w;
+    port_priv->dst_h = drw_h;
+    port_priv->drw_x = drw_x;
+    port_priv->drw_y = drw_y;
+    port_priv->w = width;
+    port_priv->h = height;
+    port_priv->pDraw = pDrawable;
+    glamor_xv_render(port_priv);
+    return Success;
+}
+
 void
 glamor_xv_init_port(glamor_port_private *port_priv)
 {
diff --git a/hw/kdrive/ephyr/ephyr_glamor_xv.c b/hw/kdrive/ephyr/ephyr_glamor_xv.c
index 3fc9747..b9c3464 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_xv.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_xv.c
@@ -97,95 +97,12 @@ ephyr_glamor_xv_put_image(KdScreenInfo *screen,
                           Bool sync,
                           RegionPtr clipBoxes, void *data)
 {
-    ScreenPtr pScreen = pDrawable->pScreen;
-    glamor_port_private *port_priv = (glamor_port_private *) data;
-    int srcPitch, srcPitch2;
-    int top, nlines;
-    int s2offset, s3offset, tmp;
-
-    s2offset = s3offset = srcPitch2 = 0;
-
-    srcPitch = width;
-    srcPitch2 = width >> 1;
-
-    if (!port_priv->src_pix[0] ||
-        (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
-        int i;
-
-        for (i = 0; i < 3; i++)
-            if (port_priv->src_pix[i])
-                glamor_destroy_pixmap(port_priv->src_pix[i]);
-
-        port_priv->src_pix[0] =
-            glamor_create_pixmap(pScreen, width, height, 8, 0);
-        port_priv->src_pix[1] =
-            glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
-        port_priv->src_pix[2] =
-            glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
-        port_priv->src_pix_w = width;
-        port_priv->src_pix_h = height;
-
-        if (!port_priv->src_pix[0] || !port_priv->src_pix[1] ||
-            !port_priv->src_pix[2])
-            return BadAlloc;
-    }
-
-    top = (src_y) & ~1;
-    nlines = (src_y + height) - top;
-
-    switch (id) {
-    case FOURCC_YV12:
-    case FOURCC_I420:
-        s2offset = srcPitch * height;
-        s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
-        s2offset += ((top >> 1) * srcPitch2);
-        s3offset += ((top >> 1) * srcPitch2);
-        if (id == FOURCC_YV12) {
-            tmp = s2offset;
-            s2offset = s3offset;
-            s3offset = tmp;
-        }
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
-                                            0, 0, srcPitch, nlines,
-                                            port_priv->src_pix[0]->devKind,
-                                            buf + (top * srcPitch), 0);
-
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
-                                            0, 0, srcPitch2, (nlines + 1) >> 1,
-                                            port_priv->src_pix[1]->devKind,
-                                            buf + s2offset, 0);
-
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
-                                            0, 0, srcPitch2, (nlines + 1) >> 1,
-                                            port_priv->src_pix[2]->devKind,
-                                            buf + s3offset, 0);
-        break;
-    default:
-        return BadMatch;
-    }
-
-    if (pDrawable->type == DRAWABLE_WINDOW)
-        port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
-    else
-        port_priv->pPixmap = (PixmapPtr) pDrawable;
-
-    if (!RegionEqual(&port_priv->clip, clipBoxes)) {
-        RegionCopy(&port_priv->clip, clipBoxes);
-    }
-
-    port_priv->src_x = src_x;
-    port_priv->src_y = src_y;
-    port_priv->src_w = src_w;
-    port_priv->src_h = src_h;
-    port_priv->dst_w = drw_w;
-    port_priv->dst_h = drw_h;
-    port_priv->drw_x = drw_x;
-    port_priv->drw_y = drw_y;
-    port_priv->w = width;
-    port_priv->h = height;
-    port_priv->pDraw = pDrawable;
-    glamor_xv_render(port_priv);
-    return Success;
+    return glamor_xv_put_image(data, pDrawable,
+                               src_x, src_y,
+                               drw_x, drw_y,
+                               src_w, src_h,
+                               drw_w, drw_h,
+                               id, buf, width, height, sync, clipBoxes);
 }
 
 void
diff --git a/hw/xfree86/glamor_egl/glamor_xf86_xv.c b/hw/xfree86/glamor_egl/glamor_xf86_xv.c
index a54c9a9..8535fa0 100644
--- a/hw/xfree86/glamor_egl/glamor_xf86_xv.c
+++ b/hw/xfree86/glamor_egl/glamor_xf86_xv.c
@@ -106,114 +106,12 @@ glamor_xf86_xv_put_image(ScrnInfoPtr pScrn,
                     Bool sync,
                     RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
 {
-    ScreenPtr screen = pDrawable->pScreen;
-    glamor_port_private *port_priv = (glamor_port_private *) data;
-    INT32 x1, x2, y1, y2;
-    int srcPitch, srcPitch2;
-    BoxRec dstBox;
-    int top, nlines;
-    int s2offset, s3offset, tmp;
-
-    s2offset = s3offset = srcPitch2 = 0;
-
-    /* Clip */
-    x1 = src_x;
-    x2 = src_x + src_w;
-    y1 = src_y;
-    y2 = src_y + src_h;
-
-    dstBox.x1 = drw_x;
-    dstBox.x2 = drw_x + drw_w;
-    dstBox.y1 = drw_y;
-    dstBox.y2 = drw_y + drw_h;
-    if (!xf86XVClipVideoHelper
-        (&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
-        return Success;
-
-    if ((x1 >= x2) || (y1 >= y2))
-        return Success;
-
-    srcPitch = width;
-    srcPitch2 = width >> 1;
-
-    if (!port_priv->src_pix[0] ||
-        (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
-        int i;
-
-        for (i = 0; i < 3; i++)
-            if (port_priv->src_pix[i])
-                glamor_destroy_pixmap(port_priv->src_pix[i]);
-
-        port_priv->src_pix[0] =
-            glamor_create_pixmap(screen, width, height, 8, 0);
-        port_priv->src_pix[1] =
-            glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
-        port_priv->src_pix[2] =
-            glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
-        port_priv->src_pix_w = width;
-        port_priv->src_pix_h = height;
-
-        if (!port_priv->src_pix[0] || !port_priv->src_pix[1] ||
-            !port_priv->src_pix[2])
-            return BadAlloc;
-    }
-
-    top = (y1 >> 16) & ~1;
-    nlines = ((y2 + 0xffff) >> 16) - top;
-
-    switch (id) {
-    case FOURCC_YV12:
-    case FOURCC_I420:
-        s2offset = srcPitch * height;
-        s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
-        s2offset += ((top >> 1) * srcPitch2);
-        s3offset += ((top >> 1) * srcPitch2);
-        if (id == FOURCC_YV12) {
-            tmp = s2offset;
-            s2offset = s3offset;
-            s3offset = tmp;
-        }
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
-                                            0, 0, srcPitch, nlines,
-                                            port_priv->src_pix[0]->devKind,
-                                            buf + (top * srcPitch), 0);
-
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
-                                            0, 0, srcPitch2, (nlines + 1) >> 1,
-                                            port_priv->src_pix[1]->devKind,
-                                            buf + s2offset, 0);
-
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
-                                            0, 0, srcPitch2, (nlines + 1) >> 1,
-                                            port_priv->src_pix[2]->devKind,
-                                            buf + s3offset, 0);
-        break;
-    default:
-        return BadMatch;
-    }
-
-    if (pDrawable->type == DRAWABLE_WINDOW)
-        port_priv->pPixmap = (*screen->GetWindowPixmap) ((WindowPtr) pDrawable);
-    else
-        port_priv->pPixmap = (PixmapPtr) pDrawable;
-
-    if (!RegionEqual(&port_priv->clip, clipBoxes)) {
-        RegionCopy(&port_priv->clip, clipBoxes);
-    }
-
-    port_priv->src_x = src_x;
-    port_priv->src_y = src_y;
-    port_priv->src_w = src_w;
-    port_priv->src_h = src_h;
-    port_priv->dst_w = drw_w;
-    port_priv->dst_h = drw_h;
-    port_priv->drw_x = drw_x;
-    port_priv->drw_y = drw_y;
-    port_priv->w = width;
-    port_priv->h = height;
-    port_priv->pDraw = pDrawable;
-    glamor_xv_render(port_priv);
-    return Success;
+    return glamor_xv_put_image(data, pDrawable,
+                               src_x, src_y,
+                               drw_x, drw_y,
+                               src_w, src_h,
+                               drw_w, drw_h,
+                               id, buf, width, height, sync, clipBoxes);
 }
 
 static XF86VideoEncodingRec DummyEncodingGLAMOR[1] = {
commit 34884e16bf7c97434e7883d025c6814e083b0def
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Apr 5 12:30:28 2014 +0100

    ephyr: Add support for XV using glamor.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am
index 00a53d0..10c5917 100644
--- a/hw/kdrive/ephyr/Makefile.am
+++ b/hw/kdrive/ephyr/Makefile.am
@@ -35,9 +35,14 @@ XV_SRCS = ephyrvideo.c
 endif
 
 if GLAMOR
+if XV
+GLAMOR_XV_SRCS = ephyr_glamor_xv.c
+endif
+
 GLAMOR_SRCS = \
 	ephyr_glamor_glx.c \
 	ephyr_glamor_glx.h \
+	$(GLAMOR_XV_SRCS)  \
 	$()
 endif
 
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index def50d8..17a862a 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -650,7 +650,9 @@ ephyrInitScreen(ScreenPtr pScreen)
 
 #ifdef XV
     if (!ephyrNoXV) {
-        if (!ephyrInitVideo(pScreen)) {
+        if (ephyr_glamor)
+            ephyr_glamor_xv_init(pScreen);
+        else if (!ephyrInitVideo(pScreen)) {
             EPHYR_LOG_ERROR("failed to initialize xvideo\n");
         }
         else {
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 34ce460..609a641 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -221,4 +221,14 @@ void ephyr_glamor_host_paint_rect(ScreenPtr pScreen);
 
 Bool ephyrInitVideo(ScreenPtr pScreen);
 
+/* ephyr_glamor_xv.c */
+#ifdef GLAMOR
+void ephyr_glamor_xv_init(ScreenPtr screen);
+#else /* !GLAMOR */
+static inline void
+ephyr_glamor_xv_init(ScreenPtr screen)
+{
+}
+#endif /* !GLAMOR */
+
 #endif
diff --git a/hw/kdrive/ephyr/ephyr_glamor_xv.c b/hw/kdrive/ephyr/ephyr_glamor_xv.c
new file mode 100644
index 0000000..3fc9747
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr_glamor_xv.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+
+#include "kdrive.h"
+#include "kxv.h"
+#include "ephyr.h"
+#include "glamor_priv.h"
+
+#include <X11/extensions/Xv.h>
+#include "fourcc.h"
+
+#define NUM_FORMATS 3
+
+static KdVideoFormatRec Formats[NUM_FORMATS] = {
+    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static void
+ephyr_glamor_xv_stop_video(KdScreenInfo *screen, void *data, Bool cleanup)
+{
+    if (!cleanup)
+        return;
+
+    glamor_xv_stop_video(data);
+}
+
+static int
+ephyr_glamor_xv_set_port_attribute(KdScreenInfo *screen,
+                                   Atom attribute, INT32 value, void *data)
+{
+    return glamor_xv_set_port_attribute(data, attribute, value);
+}
+
+static int
+ephyr_glamor_xv_get_port_attribute(KdScreenInfo *screen,
+                                   Atom attribute, INT32 *value, void *data)
+{
+    return glamor_xv_get_port_attribute(data, attribute, value);
+}
+
+static void
+ephyr_glamor_xv_query_best_size(KdScreenInfo *screen,
+                                Bool motion,
+                                short vid_w, short vid_h,
+                                short drw_w, short drw_h,
+                                unsigned int *p_w, unsigned int *p_h,
+                                void *data)
+{
+    *p_w = drw_w;
+    *p_h = drw_h;
+}
+
+static int
+ephyr_glamor_xv_query_image_attributes(KdScreenInfo *screen,
+                                       int id,
+                                       unsigned short *w, unsigned short *h,
+                                       int *pitches, int *offsets)
+{
+    return glamor_xv_query_image_attributes(id, w, h, pitches, offsets);
+}
+
+static int
+ephyr_glamor_xv_put_image(KdScreenInfo *screen,
+                          DrawablePtr pDrawable,
+                          short src_x, short src_y,
+                          short drw_x, short drw_y,
+                          short src_w, short src_h,
+                          short drw_w, short drw_h,
+                          int id,
+                          unsigned char *buf,
+                          short width,
+                          short height,
+                          Bool sync,
+                          RegionPtr clipBoxes, void *data)
+{
+    ScreenPtr pScreen = pDrawable->pScreen;
+    glamor_port_private *port_priv = (glamor_port_private *) data;
+    int srcPitch, srcPitch2;
+    int top, nlines;
+    int s2offset, s3offset, tmp;
+
+    s2offset = s3offset = srcPitch2 = 0;
+
+    srcPitch = width;
+    srcPitch2 = width >> 1;
+
+    if (!port_priv->src_pix[0] ||
+        (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
+        int i;
+
+        for (i = 0; i < 3; i++)
+            if (port_priv->src_pix[i])
+                glamor_destroy_pixmap(port_priv->src_pix[i]);
+
+        port_priv->src_pix[0] =
+            glamor_create_pixmap(pScreen, width, height, 8, 0);
+        port_priv->src_pix[1] =
+            glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
+        port_priv->src_pix[2] =
+            glamor_create_pixmap(pScreen, width >> 1, height >> 1, 8, 0);
+        port_priv->src_pix_w = width;
+        port_priv->src_pix_h = height;
+
+        if (!port_priv->src_pix[0] || !port_priv->src_pix[1] ||
+            !port_priv->src_pix[2])
+            return BadAlloc;
+    }
+
+    top = (src_y) & ~1;
+    nlines = (src_y + height) - top;
+
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+        s2offset = srcPitch * height;
+        s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
+        s2offset += ((top >> 1) * srcPitch2);
+        s3offset += ((top >> 1) * srcPitch2);
+        if (id == FOURCC_YV12) {
+            tmp = s2offset;
+            s2offset = s3offset;
+            s3offset = tmp;
+        }
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
+                                            0, 0, srcPitch, nlines,
+                                            port_priv->src_pix[0]->devKind,
+                                            buf + (top * srcPitch), 0);
+
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
+                                            0, 0, srcPitch2, (nlines + 1) >> 1,
+                                            port_priv->src_pix[1]->devKind,
+                                            buf + s2offset, 0);
+
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
+                                            0, 0, srcPitch2, (nlines + 1) >> 1,
+                                            port_priv->src_pix[2]->devKind,
+                                            buf + s3offset, 0);
+        break;
+    default:
+        return BadMatch;
+    }
+
+    if (pDrawable->type == DRAWABLE_WINDOW)
+        port_priv->pPixmap = pScreen->GetWindowPixmap((WindowPtr) pDrawable);
+    else
+        port_priv->pPixmap = (PixmapPtr) pDrawable;
+
+    if (!RegionEqual(&port_priv->clip, clipBoxes)) {
+        RegionCopy(&port_priv->clip, clipBoxes);
+    }
+
+    port_priv->src_x = src_x;
+    port_priv->src_y = src_y;
+    port_priv->src_w = src_w;
+    port_priv->src_h = src_h;
+    port_priv->dst_w = drw_w;
+    port_priv->dst_h = drw_h;
+    port_priv->drw_x = drw_x;
+    port_priv->drw_y = drw_y;
+    port_priv->w = width;
+    port_priv->h = height;
+    port_priv->pDraw = pDrawable;
+    glamor_xv_render(port_priv);
+    return Success;
+}
+
+void
+ephyr_glamor_xv_init(ScreenPtr screen)
+{
+    KdVideoAdaptorRec *adaptor;
+    glamor_port_private *port_privates;
+    KdVideoEncodingRec encoding = {
+        0,
+        "XV_IMAGE",
+        /* These sizes should probably be GL_MAX_TEXTURE_SIZE instead
+         * of 2048, but our context isn't set up yet.
+         */
+        2048, 2048,
+        {1, 1}
+    };
+    int i;
+
+    glamor_xv_core_init(screen);
+
+    adaptor = xnfcalloc(1, sizeof(*adaptor));
+
+    adaptor->name = "glamor textured video";
+    adaptor->type = XvWindowMask | XvInputMask | XvImageMask;
+    adaptor->flags = 0;
+    adaptor->nEncodings = 1;
+    adaptor->pEncodings = &encoding;
+
+    adaptor->pFormats = Formats;
+    adaptor->nFormats = NUM_FORMATS;
+
+    adaptor->nPorts = 16; /* Some absurd number */
+    port_privates = xnfcalloc(adaptor->nPorts,
+                              sizeof(glamor_port_private));
+    adaptor->pPortPrivates = xnfcalloc(adaptor->nPorts,
+                                       sizeof(glamor_port_private *));
+    for (i = 0; i < adaptor->nPorts; i++) {
+        adaptor->pPortPrivates[i].ptr = &port_privates[i];
+        glamor_xv_init_port(&port_privates[i]);
+    }
+
+    adaptor->pAttributes = glamor_xv_attributes;
+    adaptor->nAttributes = glamor_xv_num_attributes;
+
+    adaptor->pImages = glamor_xv_images;
+    adaptor->nImages = glamor_xv_num_images;
+
+    adaptor->StopVideo = ephyr_glamor_xv_stop_video;
+    adaptor->SetPortAttribute = ephyr_glamor_xv_set_port_attribute;
+    adaptor->GetPortAttribute = ephyr_glamor_xv_get_port_attribute;
+    adaptor->QueryBestSize = ephyr_glamor_xv_query_best_size;
+    adaptor->PutImage = ephyr_glamor_xv_put_image;
+    adaptor->QueryImageAttributes = ephyr_glamor_xv_query_image_attributes;
+
+    KdXVScreenInit(screen, adaptor, 1);
+}
commit 23d303bf905e76a70bda942037bdfbdcd06e55d2
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Apr 5 12:57:16 2014 +0100

    kdrive: Mark XV names const to avoid warnings.
    
    No code modifies it at runtime, and it's common to store string
    literals to it.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/src/kxv.h b/hw/kdrive/src/kxv.h
index e50615b..3a49a65 100644
--- a/hw/kdrive/src/kxv.h
+++ b/hw/kdrive/src/kxv.h
@@ -119,7 +119,7 @@ typedef enum {
 
 typedef struct {
     int id;
-    char *name;
+    const char *name;
     unsigned short width, height;
     XvRationalRec rate;
 } KdVideoEncodingRec, *KdVideoEncodingPtr;
@@ -132,7 +132,7 @@ typedef struct {
 typedef struct {
     unsigned int type;
     int flags;
-    char *name;
+    const char *name;
     int nEncodings;
     KdVideoEncodingPtr pEncodings;
     int nFormats;
commit 65efc14b6ae1ee73bf6db379d7826b6bc9fd6d33
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Apr 5 11:50:51 2014 +0100

    glamor: Split the XV code into XF86-dependent parts and generic.
    
    I want to expose this from Xephyr as well, both to be able to test XV
    changes rapidly, and beause the XV passthrough to the host's overlay
    really doesn't work out well when we glXSwapBuffers() over the
    colorkey.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index b248638..334d8fc 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -46,6 +46,7 @@ libglamor_la_SOURCES = \
 	glamor_compositerects.c\
 	glamor_utils.c\
 	glamor_utils.h\
+	glamor_xv.c \
 	glamor.h
 
 libglamor_egl_stubs_la_SOURCES = glamor_egl_stubs.c
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index f2e9260..a0b1062 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -31,6 +31,7 @@
 
 #include <xorg-server.h>
 #include "glamor.h"
+#include "xvdix.h"
 
 #include <epoxy/gl.h>
 #if GLAMOR_HAS_GBM
@@ -1053,8 +1054,22 @@ typedef struct {
     int src_pix_w, src_pix_h;
 } glamor_port_private;
 
-void glamor_init_xv_shader(ScreenPtr screen);
-void glamor_fini_xv_shader(ScreenPtr screen);
+extern XvAttributeRec glamor_xv_attributes[];
+extern int glamor_xv_num_attributes;
+extern XvImageRec glamor_xv_images[];
+extern int glamor_xv_num_images;
+
+void glamor_xv_init_port(glamor_port_private *port_priv);
+void glamor_xv_stop_video(glamor_port_private *port_priv);
+int glamor_xv_set_port_attribute(glamor_port_private *port_priv,
+                                 Atom attribute, INT32 value);
+int glamor_xv_get_port_attribute(glamor_port_private *port_priv,
+                                 Atom attribute, INT32 *value);
+int glamor_xv_query_image_attributes(int id,
+                                     unsigned short *w, unsigned short *h,
+                                     int *pitches, int *offsets);
+void glamor_xv_core_init(ScreenPtr screen);
+void glamor_xv_render(glamor_port_private *port_priv);
 
 #include"glamor_utils.h"
 
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 369b02b..4aaa866 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -36,12 +36,10 @@
 #include <dix-config.h>
 #endif
 
-#include "xf86xv.h"
-#define GLAMOR_FOR_XORG
 #include "glamor_priv.h"
 
 #include <X11/extensions/Xv.h>
-#include "fourcc.h"
+#include "../hw/xfree86/common/fourcc.h"
 /* Reference color space transform data */
 typedef struct tagREF_TRANSFORM {
     float RefLuma;
@@ -90,7 +88,28 @@ static const char *xv_ps = GLAMOR_DEFAULT_PRECISION
     "gl_FragColor = temp1;\n"
     "}\n";
 
-void
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+XvAttributeRec glamor_xv_attributes[] = {
+    {XvSettable | XvGettable, -1000, 1000, (char *)"XV_BRIGHTNESS"},
+    {XvSettable | XvGettable, -1000, 1000, (char *)"XV_CONTRAST"},
+    {XvSettable | XvGettable, -1000, 1000, (char *)"XV_SATURATION"},
+    {XvSettable | XvGettable, -1000, 1000, (char *)"XV_HUE"},
+    {XvSettable | XvGettable, 0, 1, (char *)"XV_COLORSPACE"},
+    {0, 0, 0, NULL}
+};
+int glamor_xv_num_attributes = ARRAY_SIZE(glamor_xv_attributes) - 1;
+
+Atom glamorBrightness, glamorContrast, glamorSaturation, glamorHue,
+    glamorColorspace, glamorGamma;
+
+XvImageRec glamor_xv_images[] = {
+    XVIMAGE_YV12,
+    XVIMAGE_I420,
+};
+int glamor_xv_num_images = ARRAY_SIZE(glamor_xv_images);
+
+static void
 glamor_init_xv_shader(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv;
@@ -113,43 +132,12 @@ glamor_init_xv_shader(ScreenPtr screen)
 }
 
 #define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
-#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
-
-static Atom xvBrightness, xvContrast, xvSaturation, xvHue, xvColorspace,
-    xvGamma;
-
-#define NUM_ATTRIBUTES 5
-static XF86AttributeRec Attributes_glamor[NUM_ATTRIBUTES + 1] = {
-    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
-    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
-    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
-    {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
-    {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
-    {0, 0, 0, NULL}
-};
-
-#define NUM_FORMATS 3
-
-static XF86VideoFormatRec Formats[NUM_FORMATS] = {
-    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
-};
-
-#define NUM_IMAGES 2
 
-static XF86ImageRec Images[NUM_IMAGES] = {
-    XVIMAGE_YV12,
-    XVIMAGE_I420,
-};
-
-static void
-glamor_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
+void
+glamor_xv_stop_video(glamor_port_private *port_priv)
 {
-    glamor_port_private *port_priv = (glamor_port_private *) data;
     int i;
 
-    if (!cleanup)
-        return;
-
     for (i = 0; i < 3; i++) {
         if (port_priv->src_pix[i]) {
             glamor_destroy_pixmap(port_priv->src_pix[i]);
@@ -158,46 +146,42 @@ glamor_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
     }
 }
 
-static int
-glamor_xv_set_port_attribute(ScrnInfoPtr pScrn,
-                             Atom attribute, INT32 value, void *data)
+int
+glamor_xv_set_port_attribute(glamor_port_private *port_priv,
+                             Atom attribute, INT32 value)
 {
-    glamor_port_private *port_priv = (glamor_port_private *) data;
-
-    if (attribute == xvBrightness)
+    if (attribute == glamorBrightness)
         port_priv->brightness = ClipValue(value, -1000, 1000);
-    else if (attribute == xvHue)
+    else if (attribute == glamorHue)
         port_priv->hue = ClipValue(value, -1000, 1000);
-    else if (attribute == xvContrast)
+    else if (attribute == glamorContrast)
         port_priv->contrast = ClipValue(value, -1000, 1000);
-    else if (attribute == xvSaturation)
+    else if (attribute == glamorSaturation)
         port_priv->saturation = ClipValue(value, -1000, 1000);
-    else if (attribute == xvGamma)
+    else if (attribute == glamorGamma)
         port_priv->gamma = ClipValue(value, 100, 10000);
-    else if (attribute == xvColorspace)
+    else if (attribute == glamorColorspace)
         port_priv->transform_index = ClipValue(value, 0, 1);
     else
         return BadMatch;
     return Success;
 }
 
-static int
-glamor_xv_get_port_attribute(ScrnInfoPtr pScrn,
-                             Atom attribute, INT32 *value, void *data)
+int
+glamor_xv_get_port_attribute(glamor_port_private *port_priv,
+                             Atom attribute, INT32 *value)
 {
-    glamor_port_private *port_priv = (glamor_port_private *) data;
-
-    if (attribute == xvBrightness)
+    if (attribute == glamorBrightness)
         *value = port_priv->brightness;
-    else if (attribute == xvHue)
+    else if (attribute == glamorHue)
         *value = port_priv->hue;
-    else if (attribute == xvContrast)
+    else if (attribute == glamorContrast)
         *value = port_priv->contrast;
-    else if (attribute == xvSaturation)
+    else if (attribute == glamorSaturation)
         *value = port_priv->saturation;
-    else if (attribute == xvGamma)
+    else if (attribute == glamorGamma)
         *value = port_priv->gamma;
-    else if (attribute == xvColorspace)
+    else if (attribute == glamorColorspace)
         *value = port_priv->transform_index;
     else
         return BadMatch;
@@ -205,20 +189,8 @@ glamor_xv_get_port_attribute(ScrnInfoPtr pScrn,
     return Success;
 }
 
-static void
-glamor_xv_query_best_size(ScrnInfoPtr pScrn,
-                          Bool motion,
-                          short vid_w, short vid_h,
-                          short drw_w, short drw_h,
-                          unsigned int *p_w, unsigned int *p_h, void *data)
-{
-    *p_w = drw_w;
-    *p_h = drw_h;
-}
-
-static int
-glamor_xv_query_image_attributes(ScrnInfoPtr pScrn,
-                                 int id,
+int
+glamor_xv_query_image_attributes(int id,
                                  unsigned short *w, unsigned short *h,
                                  int *pitches, int *offsets)
 {
@@ -258,8 +230,8 @@ static REF_TRANSFORM trans[2] = {
     {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}        /* BT.709 */
 };
 
-static void
-glamor_display_textured_video(glamor_port_private *port_priv)
+void
+glamor_xv_render(glamor_port_private *port_priv)
 {
     ScreenPtr screen = port_priv->pPixmap->drawable.pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -282,6 +254,9 @@ glamor_display_textured_video(glamor_port_private *port_priv)
     int ref = port_priv->transform_index;
     GLint uloc, sampler_loc;
 
+    if (!glamor_priv->xv_prog)
+        glamor_init_xv_shader(screen);
+
     cont = RTFContrast(port_priv->contrast);
     bright = RTFBrightness(port_priv->brightness);
     gamma = (float) port_priv->gamma / 1000.0;
@@ -405,202 +380,26 @@ glamor_display_textured_video(glamor_port_private *port_priv)
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
 
-static int
-glamor_xv_put_image(ScrnInfoPtr pScrn,
-                    short src_x, short src_y,
-                    short drw_x, short drw_y,
-                    short src_w, short src_h,
-                    short drw_w, short drw_h,
-                    int id,
-                    unsigned char *buf,
-                    short width,
-                    short height,
-                    Bool sync,
-                    RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
+void
+glamor_xv_init_port(glamor_port_private *port_priv)
 {
-    ScreenPtr screen = pDrawable->pScreen;
-    glamor_port_private *port_priv = (glamor_port_private *) data;
-    INT32 x1, x2, y1, y2;
-    int srcPitch, srcPitch2;
-    BoxRec dstBox;
-    int top, nlines;
-    int s2offset, s3offset, tmp;
-
-    s2offset = s3offset = srcPitch2 = 0;
-
-    /* Clip */
-    x1 = src_x;
-    x2 = src_x + src_w;
-    y1 = src_y;
-    y2 = src_y + src_h;
-
-    dstBox.x1 = drw_x;
-    dstBox.x2 = drw_x + drw_w;
-    dstBox.y1 = drw_y;
-    dstBox.y2 = drw_y + drw_h;
-    if (!xf86XVClipVideoHelper
-        (&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
-        return Success;
-
-    if ((x1 >= x2) || (y1 >= y2))
-        return Success;
-
-    srcPitch = width;
-    srcPitch2 = width >> 1;
-
-    if (!port_priv->src_pix[0] ||
-        (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
-        int i;
-
-        for (i = 0; i < 3; i++)
-            if (port_priv->src_pix[i])
-                glamor_destroy_pixmap(port_priv->src_pix[i]);
-
-        port_priv->src_pix[0] =
-            glamor_create_pixmap(screen, width, height, 8, 0);
-        port_priv->src_pix[1] =
-            glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
-        port_priv->src_pix[2] =
-            glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
-        port_priv->src_pix_w = width;
-        port_priv->src_pix_h = height;
-
-        if (!port_priv->src_pix[0] || !port_priv->src_pix[1] ||
-            !port_priv->src_pix[2])
-            return BadAlloc;
-    }
-
-    top = (y1 >> 16) & ~1;
-    nlines = ((y2 + 0xffff) >> 16) - top;
-
-    switch (id) {
-    case FOURCC_YV12:
-    case FOURCC_I420:
-        s2offset = srcPitch * height;
-        s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
-        s2offset += ((top >> 1) * srcPitch2);
-        s3offset += ((top >> 1) * srcPitch2);
-        if (id == FOURCC_YV12) {
-            tmp = s2offset;
-            s2offset = s3offset;
-            s3offset = tmp;
-        }
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
-                                            0, 0, srcPitch, nlines,
-                                            port_priv->src_pix[0]->devKind,
-                                            buf + (top * srcPitch), 0);
-
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
-                                            0, 0, srcPitch2, (nlines + 1) >> 1,
-                                            port_priv->src_pix[1]->devKind,
-                                            buf + s2offset, 0);
-
-        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
-                                            0, 0, srcPitch2, (nlines + 1) >> 1,
-                                            port_priv->src_pix[2]->devKind,
-                                            buf + s3offset, 0);
-        break;
-    default:
-        return BadMatch;
-    }
-
-    if (pDrawable->type == DRAWABLE_WINDOW)
-        port_priv->pPixmap = (*screen->GetWindowPixmap) ((WindowPtr) pDrawable);
-    else
-        port_priv->pPixmap = (PixmapPtr) pDrawable;
-
-    if (!RegionEqual(&port_priv->clip, clipBoxes)) {
-        RegionCopy(&port_priv->clip, clipBoxes);
-    }
-
-    port_priv->src_x = src_x;
-    port_priv->src_y = src_y;
-    port_priv->src_w = src_w;
-    port_priv->src_h = src_h;
-    port_priv->dst_w = drw_w;
-    port_priv->dst_h = drw_h;
-    port_priv->drw_x = drw_x;
-    port_priv->drw_y = drw_y;
-    port_priv->w = width;
-    port_priv->h = height;
-    port_priv->pDraw = pDrawable;
-    glamor_display_textured_video(port_priv);
-    return Success;
+    port_priv->brightness = 0;
+    port_priv->contrast = 0;
+    port_priv->saturation = 0;
+    port_priv->hue = 0;
+    port_priv->gamma = 1000;
+    port_priv->transform_index = 0;
+
+    REGION_NULL(pScreen, &port_priv->clip);
 }
 
-static XF86VideoEncodingRec DummyEncodingGLAMOR[1] = {
-    {
-     0,
-     "XV_IMAGE",
-     8192, 8192,
-     {1, 1}
-     }
-};
-
-XF86VideoAdaptorPtr
-glamor_xv_init(ScreenPtr screen, int num_texture_ports)
+void
+glamor_xv_core_init(ScreenPtr screen)
 {
-    glamor_port_private *port_priv;
-    XF86VideoAdaptorPtr adapt;
-    int i;
-
-    glamor_init_xv_shader(screen);
-
-    adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
-                   (sizeof(glamor_port_private) + sizeof(DevUnion)));
-    if (adapt == NULL)
-        return NULL;
-
-    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
-    xvContrast = MAKE_ATOM("XV_CONTRAST");
-    xvSaturation = MAKE_ATOM("XV_SATURATION");
-    xvHue = MAKE_ATOM("XV_HUE");
-    xvGamma = MAKE_ATOM("XV_GAMMA");
-    xvColorspace = MAKE_ATOM("XV_COLORSPACE");
-
-    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
-    adapt->flags = 0;
-    adapt->name = "GLAMOR Textured Video";
-    adapt->nEncodings = 1;
-    adapt->pEncodings = DummyEncodingGLAMOR;
-
-    adapt->nFormats = NUM_FORMATS;
-    adapt->pFormats = Formats;
-    adapt->nPorts = num_texture_ports;
-    adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
-
-    adapt->pAttributes = Attributes_glamor;
-    adapt->nAttributes = NUM_ATTRIBUTES;
-
-    port_priv =
-        (glamor_port_private *) (&adapt->pPortPrivates[num_texture_ports]);
-    adapt->pImages = Images;
-    adapt->nImages = NUM_IMAGES;
-    adapt->PutVideo = NULL;
-    adapt->PutStill = NULL;
-    adapt->GetVideo = NULL;
-    adapt->GetStill = NULL;
-    adapt->StopVideo = glamor_xv_stop_video;
-    adapt->SetPortAttribute = glamor_xv_set_port_attribute;
-    adapt->GetPortAttribute = glamor_xv_get_port_attribute;
-    adapt->QueryBestSize = glamor_xv_query_best_size;
-    adapt->PutImage = glamor_xv_put_image;
-    adapt->ReputImage = NULL;
-    adapt->QueryImageAttributes = glamor_xv_query_image_attributes;
-
-    for (i = 0; i < num_texture_ports; i++) {
-        glamor_port_private *pPriv = &port_priv[i];
-
-        pPriv->brightness = 0;
-        pPriv->contrast = 0;
-        pPriv->saturation = 0;
-        pPriv->hue = 0;
-        pPriv->gamma = 1000;
-        pPriv->transform_index = 0;
-
-        REGION_NULL(pScreen, &pPriv->clip);
-
-        adapt->pPortPrivates[i].ptr = (void *) (pPriv);
-    }
-    return adapt;
+    glamorBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+    glamorContrast = MAKE_ATOM("XV_CONTRAST");
+    glamorSaturation = MAKE_ATOM("XV_SATURATION");
+    glamorHue = MAKE_ATOM("XV_HUE");
+    glamorGamma = MAKE_ATOM("XV_GAMMA");
+    glamorColorspace = MAKE_ATOM("XV_COLORSPACE");
 }
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
index 85e1c0c..e697c82 100644
--- a/hw/xfree86/glamor_egl/Makefile.am
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -24,7 +24,7 @@ module_LTLIBRARIES = libglamoregl.la
 libglamoregl_la_SOURCES = \
 	$(top_srcdir)/glamor/glamor_egl.c \
 	$(top_srcdir)/glamor/glamor_eglmodule.c \
-	$(top_srcdir)/glamor/glamor_xv.c \
+	glamor_xf86_xv.c \
 	$()
 
 libglamoregl_la_LDFLAGS = \
@@ -38,6 +38,7 @@ libglamoregl_la_LIBADD = \
 
 AM_CPPFLAGS = $(XORG_INCS) \
 	-I$(top_srcdir)/dri3 \
+	-I$(top_srcdir)/glamor \
 	$()
 
 AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
diff --git a/hw/xfree86/glamor_egl/glamor_xf86_xv.c b/hw/xfree86/glamor_egl/glamor_xf86_xv.c
new file mode 100644
index 0000000..a54c9a9
--- /dev/null
+++ b/hw/xfree86/glamor_egl/glamor_xf86_xv.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright © 2013 Red Hat
+ *
+ * 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:
+ *      Dave Airlie <airlied at redhat.com>
+ *
+ * some code is derived from the xf86-video-ati radeon driver, mainly
+ * the calculations.
+ */
+
+/** @file glamor_xf86_xv.c
+ *
+ * This implements the XF86 XV interface, and calls into glamor core
+ * for its support of the suspiciously similar XF86 and Kdrive
+ * device-dependent XV interfaces.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#define GLAMOR_FOR_XORG
+#include "glamor_priv.h"
+
+#include <X11/extensions/Xv.h>
+#include "fourcc.h"
+
+#define NUM_FORMATS 3
+
+static XF86VideoFormatRec Formats[NUM_FORMATS] = {
+    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+static void
+glamor_xf86_xv_stop_video(ScrnInfoPtr pScrn, void *data, Bool cleanup)
+{
+    if (!cleanup)
+        return;
+
+    glamor_xv_stop_video(data);
+}
+
+static int
+glamor_xf86_xv_set_port_attribute(ScrnInfoPtr pScrn,
+                                  Atom attribute, INT32 value, void *data)
+{
+    return glamor_xv_set_port_attribute(data, attribute, value);
+}
+
+static int
+glamor_xf86_xv_get_port_attribute(ScrnInfoPtr pScrn,
+                                  Atom attribute, INT32 *value, void *data)
+{
+    return glamor_xv_get_port_attribute(data, attribute, value);
+}
+
+static void
+glamor_xf86_xv_query_best_size(ScrnInfoPtr pScrn,
+                               Bool motion,
+                               short vid_w, short vid_h,
+                               short drw_w, short drw_h,
+                               unsigned int *p_w, unsigned int *p_h, void *data)
+{
+    *p_w = drw_w;
+    *p_h = drw_h;
+}
+
+static int
+glamor_xf86_xv_query_image_attributes(ScrnInfoPtr pScrn,
+                                      int id,
+                                      unsigned short *w, unsigned short *h,
+                                      int *pitches, int *offsets)
+{
+    return glamor_xv_query_image_attributes(id, w, h, pitches, offsets);
+}
+
+static int
+glamor_xf86_xv_put_image(ScrnInfoPtr pScrn,
+                    short src_x, short src_y,
+                    short drw_x, short drw_y,
+                    short src_w, short src_h,
+                    short drw_w, short drw_h,
+                    int id,
+                    unsigned char *buf,
+                    short width,
+                    short height,
+                    Bool sync,
+                    RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
+{
+    ScreenPtr screen = pDrawable->pScreen;
+    glamor_port_private *port_priv = (glamor_port_private *) data;
+    INT32 x1, x2, y1, y2;
+    int srcPitch, srcPitch2;
+    BoxRec dstBox;
+    int top, nlines;
+    int s2offset, s3offset, tmp;
+
+    s2offset = s3offset = srcPitch2 = 0;
+
+    /* Clip */
+    x1 = src_x;
+    x2 = src_x + src_w;
+    y1 = src_y;
+    y2 = src_y + src_h;
+
+    dstBox.x1 = drw_x;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y1 = drw_y;
+    dstBox.y2 = drw_y + drw_h;
+    if (!xf86XVClipVideoHelper
+        (&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
+        return Success;
+
+    if ((x1 >= x2) || (y1 >= y2))
+        return Success;
+
+    srcPitch = width;
+    srcPitch2 = width >> 1;
+
+    if (!port_priv->src_pix[0] ||
+        (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
+        int i;
+
+        for (i = 0; i < 3; i++)
+            if (port_priv->src_pix[i])
+                glamor_destroy_pixmap(port_priv->src_pix[i]);
+
+        port_priv->src_pix[0] =
+            glamor_create_pixmap(screen, width, height, 8, 0);
+        port_priv->src_pix[1] =
+            glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
+        port_priv->src_pix[2] =
+            glamor_create_pixmap(screen, width >> 1, height >> 1, 8, 0);
+        port_priv->src_pix_w = width;
+        port_priv->src_pix_h = height;
+
+        if (!port_priv->src_pix[0] || !port_priv->src_pix[1] ||
+            !port_priv->src_pix[2])
+            return BadAlloc;
+    }
+
+    top = (y1 >> 16) & ~1;
+    nlines = ((y2 + 0xffff) >> 16) - top;
+
+    switch (id) {
+    case FOURCC_YV12:
+    case FOURCC_I420:
+        s2offset = srcPitch * height;
+        s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
+        s2offset += ((top >> 1) * srcPitch2);
+        s3offset += ((top >> 1) * srcPitch2);
+        if (id == FOURCC_YV12) {
+            tmp = s2offset;
+            s2offset = s3offset;
+            s3offset = tmp;
+        }
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[0],
+                                            0, 0, srcPitch, nlines,
+                                            port_priv->src_pix[0]->devKind,
+                                            buf + (top * srcPitch), 0);
+
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[1],
+                                            0, 0, srcPitch2, (nlines + 1) >> 1,
+                                            port_priv->src_pix[1]->devKind,
+                                            buf + s2offset, 0);
+
+        glamor_upload_sub_pixmap_to_texture(port_priv->src_pix[2],
+                                            0, 0, srcPitch2, (nlines + 1) >> 1,
+                                            port_priv->src_pix[2]->devKind,
+                                            buf + s3offset, 0);
+        break;
+    default:
+        return BadMatch;
+    }
+
+    if (pDrawable->type == DRAWABLE_WINDOW)
+        port_priv->pPixmap = (*screen->GetWindowPixmap) ((WindowPtr) pDrawable);
+    else
+        port_priv->pPixmap = (PixmapPtr) pDrawable;
+
+    if (!RegionEqual(&port_priv->clip, clipBoxes)) {
+        RegionCopy(&port_priv->clip, clipBoxes);
+    }
+
+    port_priv->src_x = src_x;
+    port_priv->src_y = src_y;
+    port_priv->src_w = src_w;
+    port_priv->src_h = src_h;
+    port_priv->dst_w = drw_w;
+    port_priv->dst_h = drw_h;
+    port_priv->drw_x = drw_x;
+    port_priv->drw_y = drw_y;
+    port_priv->w = width;
+    port_priv->h = height;
+    port_priv->pDraw = pDrawable;
+    glamor_xv_render(port_priv);
+    return Success;
+}
+
+static XF86VideoEncodingRec DummyEncodingGLAMOR[1] = {
+    {
+     0,
+     "XV_IMAGE",
+     8192, 8192,
+     {1, 1}
+     }
+};
+
+XF86VideoAdaptorPtr
+glamor_xv_init(ScreenPtr screen, int num_texture_ports)
+{
+    glamor_port_private *port_priv;
+    XF86VideoAdaptorPtr adapt;
+    int i;
+
+    glamor_xv_core_init(screen);
+
+    adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
+                   (sizeof(glamor_port_private) + sizeof(DevUnion)));
+    if (adapt == NULL)
+        return NULL;
+
+    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+    adapt->flags = 0;
+    adapt->name = "GLAMOR Textured Video";
+    adapt->nEncodings = 1;
+    adapt->pEncodings = DummyEncodingGLAMOR;
+
+    adapt->nFormats = NUM_FORMATS;
+    adapt->pFormats = Formats;
+    adapt->nPorts = num_texture_ports;
+    adapt->pPortPrivates = (DevUnion *) (&adapt[1]);
+
+    adapt->pAttributes = glamor_xv_attributes;
+    adapt->nAttributes = glamor_xv_num_attributes;
+
+    port_priv =
+        (glamor_port_private *) (&adapt->pPortPrivates[num_texture_ports]);
+    adapt->pImages = glamor_xv_images;
+    adapt->nImages = glamor_xv_num_images;
+    adapt->PutVideo = NULL;
+    adapt->PutStill = NULL;
+    adapt->GetVideo = NULL;
+    adapt->GetStill = NULL;
+    adapt->StopVideo = glamor_xf86_xv_stop_video;
+    adapt->SetPortAttribute = glamor_xf86_xv_set_port_attribute;
+    adapt->GetPortAttribute = glamor_xf86_xv_get_port_attribute;
+    adapt->QueryBestSize = glamor_xf86_xv_query_best_size;
+    adapt->PutImage = glamor_xf86_xv_put_image;
+    adapt->ReputImage = NULL;
+    adapt->QueryImageAttributes = glamor_xf86_xv_query_image_attributes;
+
+    for (i = 0; i < num_texture_ports; i++) {
+        glamor_port_private *pPriv = &port_priv[i];
+
+        pPriv->brightness = 0;
+        pPriv->contrast = 0;
+        pPriv->saturation = 0;
+        pPriv->hue = 0;
+        pPriv->gamma = 1000;
+        pPriv->transform_index = 0;
+
+        REGION_NULL(pScreen, &pPriv->clip);
+
+        adapt->pPortPrivates[i].ptr = (void *) (pPriv);
+    }
+    return adapt;
+}
commit a5662193f1c3dd63f615d96d1a300f70086ccbc6
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Apr 5 12:26:33 2014 +0100

    kdrive: Simplify the adaptor setup interface.
    
    Now that we don't have to worry about the generic adaptors code,
    there's no need to have a list of pointers to different sets of
    adaptors.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c
index 4c9d13a..ab18c7a 100644
--- a/hw/kdrive/ephyr/ephyrvideo.c
+++ b/hw/kdrive/ephyr/ephyrvideo.c
@@ -613,8 +613,6 @@ static Bool
 ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
 {
     Bool is_ok = FALSE;
-    KdVideoAdaptorPtr *adaptors = NULL, *registered_adaptors = NULL;
-    int num_registered_adaptors = 0, i = 0, num_adaptors = 0;
 
     EPHYR_RETURN_VAL_IF_FAIL(a_this && a_screen, FALSE);
 
@@ -623,28 +621,14 @@ ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
     if (!a_this->num_adaptors)
         goto out;
 
-    num_adaptors = a_this->num_adaptors;
-    adaptors = calloc(num_adaptors, sizeof(KdVideoAdaptorPtr));
-    if (!adaptors) {
-        EPHYR_LOG_ERROR("failed to allocate adaptors tab\n");
-        goto out;
-    }
-    memmove(adaptors, registered_adaptors, num_registered_adaptors);
-    for (i = 0; i < a_this->num_adaptors; i++) {
-        *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i];
-    }
-    if (!KdXVScreenInit(a_screen, adaptors, num_adaptors)) {
+    if (!KdXVScreenInit(a_screen, a_this->adaptors, a_this->num_adaptors)) {
         EPHYR_LOG_ERROR("failed to register adaptors\n");
         goto out;
     }
-    EPHYR_LOG("there are  %d registered adaptors\n", num_adaptors);
+    EPHYR_LOG("there are  %d registered adaptors\n", a_this->num_adaptors);
     is_ok = TRUE;
 
  out:
-    free(registered_adaptors);
-    registered_adaptors = NULL;
-    free(adaptors);
-    adaptors = NULL;
 
     EPHYR_LOG("leave\n");
     return is_ok;
diff --git a/hw/kdrive/src/kxv.c b/hw/kdrive/src/kxv.c
index d1c4530..60a8345 100644
--- a/hw/kdrive/src/kxv.c
+++ b/hw/kdrive/src/kxv.c
@@ -98,7 +98,7 @@ static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
 static void KdXVClipNotify(WindowPtr pWin, int dx, int dy);
 
 /* misc */
-static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr *, int);
+static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr, int);
 
 static DevPrivateKeyRec KdXVWindowKeyRec;
 
@@ -129,7 +129,7 @@ KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr)
 }
 
 Bool
-KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr * adaptors, int num)
+KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr adaptors, int num)
 {
     KdXVScreenPtr ScreenPriv;
     XvScreenPtr pxvs;
@@ -239,7 +239,7 @@ KdXVFreeAdaptor(XvAdaptorPtr pAdaptor)
 }
 
 static Bool
-KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
+KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr infoPtr, int number)
 {
     KdScreenPriv(pScreen);
     KdScreenInfo *screen = pScreenPriv->screen;
@@ -268,7 +268,7 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
         return FALSE;
 
     for (pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
-        adaptorPtr = infoPtr[na];
+        adaptorPtr = &infoPtr[na];
 
         if (!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
             !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
diff --git a/hw/kdrive/src/kxv.h b/hw/kdrive/src/kxv.h
index 13efcbd..e50615b 100644
--- a/hw/kdrive/src/kxv.h
+++ b/hw/kdrive/src/kxv.h
@@ -157,7 +157,7 @@ typedef struct {
 } KdVideoAdaptorRec, *KdVideoAdaptorPtr;
 
 Bool
- KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr * Adaptors, int num);
+ KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr Adaptors, int num);
 
 void
 
commit 55aad7399d4470bc46c064aafe07d12a6c293982
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Apr 4 12:09:01 2014 +0100

    kdrive: Remove dead generic XV adaptors code.
    
    I couldn't find any callers in the history of the tree.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c
index 160c965..4c9d13a 100644
--- a/hw/kdrive/ephyr/ephyrvideo.c
+++ b/hw/kdrive/ephyr/ephyrvideo.c
@@ -612,8 +612,6 @@ ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this)
 static Bool
 ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
 {
-    KdScreenPriv(a_screen);
-    KdScreenInfo *screen = pScreenPriv->screen;
     Bool is_ok = FALSE;
     KdVideoAdaptorPtr *adaptors = NULL, *registered_adaptors = NULL;
     int num_registered_adaptors = 0, i = 0, num_adaptors = 0;
@@ -624,10 +622,8 @@ ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
 
     if (!a_this->num_adaptors)
         goto out;
-    num_registered_adaptors =
-        KdXVListGenericAdaptors(screen, &registered_adaptors);
 
-    num_adaptors = num_registered_adaptors + a_this->num_adaptors;
+    num_adaptors = a_this->num_adaptors;
     adaptors = calloc(num_adaptors, sizeof(KdVideoAdaptorPtr));
     if (!adaptors) {
         EPHYR_LOG_ERROR("failed to allocate adaptors tab\n");
diff --git a/hw/kdrive/src/kxv.c b/hw/kdrive/src/kxv.c
index 5085770..d1c4530 100644
--- a/hw/kdrive/src/kxv.c
+++ b/hw/kdrive/src/kxv.c
@@ -116,49 +116,6 @@ static unsigned long PortResource = 0;
 #define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \
     dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey))
 
-static KdXVInitGenericAdaptorPtr *GenDrivers = NULL;
-static int NumGenDrivers = 0;
-
-int
-KdXVRegisterGenericAdaptorDriver(KdXVInitGenericAdaptorPtr InitFunc)
-{
-    KdXVInitGenericAdaptorPtr *newdrivers;
-
-/*   fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */
-
-    newdrivers = realloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) *
-                         (1 + NumGenDrivers));
-    if (!newdrivers)
-        return 0;
-    GenDrivers = newdrivers;
-
-    GenDrivers[NumGenDrivers++] = InitFunc;
-
-    return 1;
-}
-
-int
-KdXVListGenericAdaptors(KdScreenInfo * screen, KdVideoAdaptorPtr ** adaptors)
-{
-    int i, j, n, num;
-    KdVideoAdaptorPtr *DrivAdap, *new;
-
-    num = 0;
-    *adaptors = NULL;
-    for (i = 0; i < NumGenDrivers; i++) {
-        n = GenDrivers[i] (screen, &DrivAdap);
-        if (0 == n)
-            continue;
-        new = realloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num + n));
-        if (NULL == new)
-            continue;
-        *adaptors = new;
-        for (j = 0; j < n; j++, num++)
-            (*adaptors)[num] = DrivAdap[j];
-    }
-    return num;
-}
-
 KdVideoAdaptorPtr
 KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen)
 {
diff --git a/hw/kdrive/src/kxv.h b/hw/kdrive/src/kxv.h
index f479de1..13efcbd 100644
--- a/hw/kdrive/src/kxv.h
+++ b/hw/kdrive/src/kxv.h
@@ -159,15 +159,6 @@ typedef struct {
 Bool
  KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr * Adaptors, int num);
 
-typedef int (*KdXVInitGenericAdaptorPtr) (KdScreenInfo * screen,
-                                          KdVideoAdaptorPtr ** Adaptors);
-
-int
- KdXVRegisterGenericAdaptorDriver(KdXVInitGenericAdaptorPtr InitFunc);
-
-int
- KdXVListGenericAdaptors(KdScreenInfo * screen, KdVideoAdaptorPtr ** Adaptors);
-
 void
 
 KdXVCopyPackedData(KdScreenInfo * screen, CARD8 *src, CARD8 *dst, int randr,
commit 0edc0a78fbfac4578b0f809aef17332c1eb461e3
Author: Eric Anholt <eric at anholt.net>
Date:   Sun Apr 6 08:12:35 2014 +0100

    kdrive: Do a little more cleanup from the XV struct deduplication.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c
index c672835..160c965 100644
--- a/hw/kdrive/ephyr/ephyrvideo.c
+++ b/hw/kdrive/ephyr/ephyrvideo.c
@@ -69,7 +69,7 @@ static Bool ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this);
 static Bool ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this,
                                         ScreenPtr a_screen);
 
-static Bool ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs,
+static Bool ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,
                                         int a_attrs_len,
                                         const char *a_attr_name,
                                         int a_attr_value, Bool *a_is_valid);
@@ -363,7 +363,7 @@ translate_xv_attributes(KdVideoAdaptorPtr adaptor,
 
     it = xcb_xv_query_port_attributes_attributes_iterator(reply);
     for (i = 0; i < reply->num_attributes; i++) {
-        KdAttributePtr attribute = &adaptor->pAttributes[i];
+        XvAttributePtr attribute = &adaptor->pAttributes[i];
 
         attribute->flags = it.data->flags;
         attribute->min_value = it.data->min;
@@ -397,7 +397,7 @@ translate_xv_image_formats(KdVideoAdaptorPtr adaptor,
         return FALSE;
 
     adaptor->nImages = reply->num_formats;
-    adaptor->pImages = calloc(reply->num_formats, sizeof(KdImageRec));
+    adaptor->pImages = calloc(reply->num_formats, sizeof(XvImageRec));
     if (!adaptor->pImages) {
         free(reply);
         return FALSE;
@@ -405,7 +405,7 @@ translate_xv_image_formats(KdVideoAdaptorPtr adaptor,
 
     formats = xcb_xv_list_image_formats_format(reply);
     for (i = 0; i < reply->num_formats; i++) {
-        KdImagePtr image = &adaptor->pImages[i];
+        XvImagePtr image = &adaptor->pImages[i];
 
         image->id = formats[i].id;
         image->type = formats[i].type;
@@ -655,7 +655,7 @@ ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
 }
 
 static Bool
-ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs,
+ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,
                             int a_attrs_len,
                             const char *a_attr_name,
                             int a_attr_value, Bool *a_is_valid)
diff --git a/hw/kdrive/src/kxv.c b/hw/kdrive/src/kxv.c
index 9cc0edd..5085770 100644
--- a/hw/kdrive/src/kxv.c
+++ b/hw/kdrive/src/kxv.c
@@ -295,15 +295,11 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
     XvPortRecPrivatePtr portPriv;
     XvPortPtr pPort, pp;
     int numPort;
-    KdAttributePtr attributePtr;
-    XvAttributePtr pAttribute, pat;
     KdVideoFormatPtr formatPtr;
     XvFormatPtr pFormat, pf;
     int numFormat, totFormat;
     KdVideoEncodingPtr encodingPtr;
     XvEncodingPtr pEncode, pe;
-    KdImagePtr imagePtr;
-    XvImagePtr pImage, pi;
     int numVisuals;
     VisualPtr pVisual;
     int i;
@@ -381,26 +377,24 @@ KdXVInitAdaptors(ScreenPtr pScreen, KdVideoAdaptorPtr * infoPtr, int number)
         }
 
         if (adaptorPtr->nImages &&
-            (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
-
-            for (i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
-                 i < adaptorPtr->nImages; i++, pi++, imagePtr++) {
-                memcpy(pi, imagePtr, sizeof(*pi));
-            }
+            (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
+            memcpy(pa->pImages, adaptorPtr->pImages,
+                   adaptorPtr->nImages * sizeof(XvImageRec));
             pa->nImages = adaptorPtr->nImages;
-            pa->pImages = pImage;
         }
 
         if (adaptorPtr->nAttributes &&
-            (pAttribute =
-             calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) {
-            for (pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i =
-                 0; i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) {
-                memcpy(pat, attributePtr, sizeof(*pat));
-                pat->name = strdup(attributePtr->name);
+            (pa->pAttributes = calloc(adaptorPtr->nAttributes,
+                                      sizeof(XvAttributeRec)))) {
+            memcpy(pa->pAttributes, adaptorPtr->pAttributes,
+                   adaptorPtr->nAttributes * sizeof(XvAttributeRec));
+
+            for (i = 0; i < adaptorPtr->nAttributes; i++) {
+                pa->pAttributes[i].name =
+                    strdup(adaptorPtr->pAttributes[i].name);
             }
+
             pa->nAttributes = adaptorPtr->nAttributes;
-            pa->pAttributes = pAttribute;
         }
 
         totFormat = adaptorPtr->nFormats;
diff --git a/hw/kdrive/src/kxv.h b/hw/kdrive/src/kxv.h
index 85a030e..f479de1 100644
--- a/hw/kdrive/src/kxv.h
+++ b/hw/kdrive/src/kxv.h
@@ -56,8 +56,6 @@ of the copyright holder.
 #define VIDEO_OVERLAID_STILLS			0x00000008
 #define VIDEO_CLIP_TO_VIEWPORT			0x00000010
 
-typedef XvImageRec KdImageRec, *KdImagePtr;
-
 typedef struct {
     KdScreenInfo *screen;
     int id;
@@ -131,8 +129,6 @@ typedef struct {
     short class;
 } KdVideoFormatRec, *KdVideoFormatPtr;
 
-typedef XvAttributeRec KdAttributeRec, *KdAttributePtr;
-
 typedef struct {
     unsigned int type;
     int flags;
@@ -144,9 +140,9 @@ typedef struct {
     int nPorts;
     DevUnion *pPortPrivates;
     int nAttributes;
-    KdAttributePtr pAttributes;
+    XvAttributePtr pAttributes;
     int nImages;
-    KdImagePtr pImages;
+    XvImagePtr pImages;
     PutVideoFuncPtr PutVideo;
     PutStillFuncPtr PutStill;
     GetVideoFuncPtr GetVideo;
commit 1d90e8811a7d4db328c0c944bec0aa3ed6afb70d
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 21:34:44 2013 -0800

    xorg: Remove duplicated definitions of some XV-related structs.
    
    These were field-for-field identical, so we can just typedef them to
    be the same, and memcpy their contents.
    
    v2: Fix missed strdup().
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/xfree86/common/xf86xv.c b/hw/xfree86/common/xf86xv.c
index b16cb5d..e212a73 100644
--- a/hw/xfree86/common/xf86xv.c
+++ b/hw/xfree86/common/xf86xv.c
@@ -359,15 +359,11 @@ xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
     XvPortRecPrivatePtr portPriv;
     XvPortPtr pPort, pp;
     int numPort;
-    XF86AttributePtr attributePtr;
-    XvAttributePtr pAttribute, pat;
     XF86VideoFormatPtr formatPtr;
     XvFormatPtr pFormat, pf;
     int numFormat, totFormat;
     XF86VideoEncodingPtr encodingPtr;
     XvEncodingPtr pEncode, pe;
-    XF86ImagePtr imagePtr;
-    XvImagePtr pImage, pi;
     int numVisuals;
     VisualPtr pVisual;
     int i;
@@ -445,49 +441,24 @@ xf86XVInitAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr * infoPtr, int number)
         }
 
         if (adaptorPtr->nImages &&
-            (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
-
-            for (i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
-                 i < adaptorPtr->nImages; i++, pi++, imagePtr++) {
-                pi->id = imagePtr->id;
-                pi->type = imagePtr->type;
-                pi->byte_order = imagePtr->byte_order;
-                memcpy(pi->guid, imagePtr->guid, 16);
-                pi->bits_per_pixel = imagePtr->bits_per_pixel;
-                pi->format = imagePtr->format;
-                pi->num_planes = imagePtr->num_planes;
-                pi->depth = imagePtr->depth;
-                pi->red_mask = imagePtr->red_mask;
-                pi->green_mask = imagePtr->green_mask;
-                pi->blue_mask = imagePtr->blue_mask;
-                pi->y_sample_bits = imagePtr->y_sample_bits;
-                pi->u_sample_bits = imagePtr->u_sample_bits;
-                pi->v_sample_bits = imagePtr->v_sample_bits;
-                pi->horz_y_period = imagePtr->horz_y_period;
-                pi->horz_u_period = imagePtr->horz_u_period;
-                pi->horz_v_period = imagePtr->horz_v_period;
-                pi->vert_y_period = imagePtr->vert_y_period;
-                pi->vert_u_period = imagePtr->vert_u_period;
-                pi->vert_v_period = imagePtr->vert_v_period;
-                memcpy(pi->component_order, imagePtr->component_order, 32);
-                pi->scanline_order = imagePtr->scanline_order;
-            }
+            (pa->pImages = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
+            memcpy(pa->pImages, adaptorPtr->pImages,
+                   adaptorPtr->nImages * sizeof(XvImageRec));
             pa->nImages = adaptorPtr->nImages;
-            pa->pImages = pImage;
         }
 
         if (adaptorPtr->nAttributes &&
-            (pAttribute =
-             calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) {
-            for (pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i =
-                 0; i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) {
-                pat->flags = attributePtr->flags;
-                pat->min_value = attributePtr->min_value;
-                pat->max_value = attributePtr->max_value;
-                pat->name = strdup(attributePtr->name);
+            (pa->pAttributes = calloc(adaptorPtr->nAttributes,
+                                      sizeof(XvAttributeRec)))) {
+            memcpy(pa->pAttributes, adaptorPtr->pAttributes,
+                   adaptorPtr->nAttributes * sizeof(XvAttributeRec));
+
+            for (i = 0; i < adaptorPtr->nAttributes; i++) {
+                pa->pAttributes[i].name =
+                    strdup(adaptorPtr->pAttributes[i].name);
             }
+
             pa->nAttributes = adaptorPtr->nAttributes;
-            pa->pAttributes = pAttribute;
         }
 
         totFormat = adaptorPtr->nFormats;
diff --git a/hw/xfree86/common/xf86xv.h b/hw/xfree86/common/xf86xv.h
index 8986e2e..de17eb1 100644
--- a/hw/xfree86/common/xf86xv.h
+++ b/hw/xfree86/common/xf86xv.h
@@ -42,34 +42,7 @@
  */
 #define VIDEO_CLIP_TO_VIEWPORT			0x00000010
 
-typedef struct {
-    int id;
-    int type;
-    int byte_order;
-    unsigned char guid[16];
-    int bits_per_pixel;
-    int format;
-    int num_planes;
-
-    /* for RGB formats only */
-    int depth;
-    unsigned int red_mask;
-    unsigned int green_mask;
-    unsigned int blue_mask;
-
-    /* for YUV formats only */
-    unsigned int y_sample_bits;
-    unsigned int u_sample_bits;
-    unsigned int v_sample_bits;
-    unsigned int horz_y_period;
-    unsigned int horz_u_period;
-    unsigned int horz_v_period;
-    unsigned int vert_y_period;
-    unsigned int vert_u_period;
-    unsigned int vert_v_period;
-    char component_order[32];
-    int scanline_order;
-} XF86ImageRec, *XF86ImagePtr;
+typedef XvImageRec XF86ImageRec, *XF86ImagePtr;
 
 typedef struct {
     ScrnInfoPtr pScrn;
@@ -147,12 +120,7 @@ typedef struct {
     short class;
 } XF86VideoFormatRec, *XF86VideoFormatPtr;
 
-typedef struct {
-    int flags;
-    int min_value;
-    int max_value;
-    const char *name;
-} XF86AttributeRec, *XF86AttributePtr;
+typedef XvAttributeRec XF86AttributeRec, *XF86AttributePtr;
 
 typedef struct {
     unsigned int type;
commit a6aaa51752f301de24abce264976ba3c3a50863c
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 14:55:47 2014 -0700

    glamor: Remove stubbed-out glamor_stipple function
    
    This function isn't used anymore.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index bafc420..737b274 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -292,17 +292,6 @@ glamor_fini_finish_access_shaders(ScreenPtr screen)
     glDeleteProgram(glamor_priv->finish_access_prog[1]);
 }
 
-Bool
-glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
-               int x, int y, int width, int height,
-               unsigned char alu, unsigned long planemask,
-               unsigned long fg_pixel, unsigned long bg_pixel,
-               int stipple_x, int stipple_y)
-{
-    glamor_fallback("stubbed out stipple depth %d\n", pixmap->drawable.depth);
-    return FALSE;
-}
-
 GCOps glamor_gc_ops = {
     .FillSpans = glamor_fill_spans,
     .SetSpans = glamor_set_spans,
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 6cb074e..f2e9260 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -648,11 +648,6 @@ void glamor_fini_finish_access_shaders(ScreenPtr screen);
 const Bool glamor_get_drawable_location(const DrawablePtr drawable);
 void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap,
                                 int *x, int *y);
-Bool glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
-                    int x, int y, int width, int height,
-                    unsigned char alu, unsigned long planemask,
-                    unsigned long fg_pixel, unsigned long bg_pixel,
-                    int stipple_x, int stipple_y);
 GLint glamor_compile_glsl_prog(GLenum type, const char *source);
 void glamor_link_glsl_prog(ScreenPtr screen, GLint prog,
                            const char *format, ...) _X_ATTRIBUTE_PRINTF(3,4);
commit ef2bf0e645ed8242a0b637ed6a9d5b8c03b6b481
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 14:30:33 2014 -0700

    glamor: Remove 'tiling' shader code
    
    The core rendering paths all use the glamor_program fill functions now
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 30fcef1..b248638 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -32,7 +32,6 @@ libglamor_la_SOURCES = \
 	glamor_transform.c \
 	glamor_transform.h \
 	glamor_trapezoid.c \
-	glamor_tile.c \
 	glamor_triangles.c\
 	glamor_addtraps.c\
 	glamor_glyphblt.c\
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 6891881..9fb9c67 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -514,7 +514,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 
     glamor_init_vbo(screen);
     glamor_init_pixmap_fbo(screen);
-    glamor_init_tile_shader(screen);
 #ifdef GLAMOR_TRAPEZOID_SHADER
     glamor_init_trapezoid_shader(screen);
 #endif
@@ -546,7 +545,6 @@ glamor_release_screen_priv(ScreenPtr screen)
 #endif
     glamor_fini_vbo(screen);
     glamor_fini_pixmap_fbo(screen);
-    glamor_fini_tile_shader(screen);
 #ifdef GLAMOR_TRAPEZOID_SHADER
     glamor_fini_trapezoid_shader(screen);
 #endif
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 187a9b5..6cb074e 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -273,10 +273,6 @@ typedef struct glamor_screen_private {
     GLint finish_access_revert[2];
     GLint finish_access_swap_rb[2];
 
-    /* glamor_tile */
-    GLint tile_prog;
-    GLint tile_wh;
-
     /* glamor gradient, 0 for small nstops, 1 for
        large nstops and 2 for dynamic generate. */
     GLint gradient_prog[SHADER_GRADIENT_COUNT][3];
@@ -760,14 +756,6 @@ void glamor_trapezoids(CARD8 op,
                        PictFormatPtr mask_format, INT16 x_src, INT16 y_src,
                        int ntrap, xTrapezoid *traps);
 
-/* glamor_tile.c */
-Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
-                 int x, int y, int width, int height,
-                 unsigned char alu, unsigned long planemask,
-                 int tile_x, int tile_y);
-void glamor_init_tile_shader(ScreenPtr screen);
-void glamor_fini_tile_shader(ScreenPtr screen);
-
 /* glamor_gradient.c */
 void glamor_init_gradient_shader(ScreenPtr screen);
 void glamor_fini_gradient_shader(ScreenPtr screen);
diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c
deleted file mode 100644
index 4e47976..0000000
--- a/glamor/glamor_tile.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric at anholt.net>
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- *
- */
-
-#include "glamor_priv.h"
-
-/** @file glamor_tile.c
- *
- * Implements the basic fill-with-a-tile support used by multiple GC ops.
- */
-
-void
-glamor_init_tile_shader(ScreenPtr screen)
-{
-    glamor_screen_private *glamor_priv;
-    const char *tile_vs =
-        "attribute vec4 v_position;\n"
-        "attribute vec4 v_texcoord0;\n"
-        "varying vec2 tile_texture;\n"
-        "void main()\n"
-        "{\n"
-        "       gl_Position = v_position;\n"
-        "       tile_texture = v_texcoord0.xy;\n"
-        "}\n";
-    const char *tile_fs =
-        GLAMOR_DEFAULT_PRECISION
-        "varying vec2 tile_texture;\n"
-        "uniform sampler2D sampler;\n"
-        "uniform vec2	wh;"
-        "void main()\n"
-        "{\n"
-        "   vec2 rel_tex;"
-        "   rel_tex = tile_texture * wh; \n"
-        "   rel_tex = floor(rel_tex) + (fract(rel_tex) / wh); \n"
-        "	gl_FragColor = texture2D(sampler, rel_tex);\n"
-        "}\n";
-    GLint fs_prog, vs_prog;
-    GLint sampler_uniform_location;
-
-    glamor_priv = glamor_get_screen_private(screen);
-    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);
-    glAttachShader(glamor_priv->tile_prog, vs_prog);
-    glAttachShader(glamor_priv->tile_prog, fs_prog);
-
-    glBindAttribLocation(glamor_priv->tile_prog,
-                         GLAMOR_VERTEX_POS, "v_position");
-    glBindAttribLocation(glamor_priv->tile_prog,
-                         GLAMOR_VERTEX_SOURCE, "v_texcoord0");
-    glamor_link_glsl_prog(screen, glamor_priv->tile_prog, "tile");
-
-    sampler_uniform_location =
-        glGetUniformLocation(glamor_priv->tile_prog, "sampler");
-    glUseProgram(glamor_priv->tile_prog);
-    glUniform1i(sampler_uniform_location, 0);
-
-    glamor_priv->tile_wh =
-        glGetUniformLocation(glamor_priv->tile_prog, "wh");
-}
-
-void
-glamor_fini_tile_shader(ScreenPtr screen)
-{
-    glamor_screen_private *glamor_priv;
-
-    glamor_priv = glamor_get_screen_private(screen);
-    glamor_make_current(glamor_priv);
-    glDeleteProgram(glamor_priv->tile_prog);
-}
-
-static void
-_glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
-             int x, int y, int width, int height, int tile_x, int tile_y)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    int x1 = x;
-    int x2 = x + width;
-    int y1 = y;
-    int y2 = y + height;
-    int tile_x1 = tile_x;
-    int tile_x2 = tile_x + width;
-    int tile_y1 = tile_y;
-    int tile_y2 = tile_y + height;
-    float vertices[8];
-    float source_texcoords[8];
-    GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
-    glamor_pixmap_private *src_pixmap_priv;
-    glamor_pixmap_private *dst_pixmap_priv;
-    float wh[4];
-
-    src_pixmap_priv = glamor_get_pixmap_private(tile);
-    dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    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_make_current(glamor_priv);
-    glUseProgram(glamor_priv->tile_prog);
-
-    glamor_pixmap_fbo_fix_wh_ratio(wh, src_pixmap_priv);
-    glUniform2fv(glamor_priv->tile_wh, 1, wh);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    glamor_set_repeat_normalize_tcoords
-        (src_pixmap_priv, RepeatNormal,
-         src_xscale, src_yscale,
-         tile_x1, tile_y1,
-         tile_x2, tile_y2, glamor_priv->yInverted, source_texcoords);
-
-    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
-                          2 * sizeof(float), source_texcoords);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-
-    glamor_set_normalize_vcoords(dst_pixmap_priv, dst_xscale, dst_yscale,
-                                 x1, y1,
-                                 x2, y2, glamor_priv->yInverted, vertices);
-
-    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
-                          2 * sizeof(float), vertices);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
-    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-
-    glamor_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
-}
-
-Bool
-glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
-            int x, int y, int width, int height,
-            unsigned char alu, unsigned long planemask, int tile_x, int tile_y)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_pixmap_private *dst_pixmap_priv;
-    glamor_pixmap_private *src_pixmap_priv;
-
-    dst_pixmap_priv = glamor_get_pixmap_private(pixmap);
-    src_pixmap_priv = glamor_get_pixmap_private(tile);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
-        return FALSE;
-
-    if (glamor_priv->tile_prog == 0) {
-        glamor_fallback("Tiling unsupported\n");
-        goto fail;
-    }
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
-        /* XXX dynamic uploading candidate. */
-        glamor_fallback("Non-texture tile pixmap\n");
-        goto fail;
-    }
-
-    if (!glamor_set_planemask(pixmap, planemask)) {
-        glamor_fallback("unsupported planemask %lx\n", planemask);
-        goto fail;
-    }
-
-    glamor_make_current(glamor_priv);
-    if (!glamor_set_alu(screen, alu)) {
-        glamor_fallback("unsupported alu %x\n", alu);
-        goto fail;
-    }
-
-    if (dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
-        || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
-        glamor_pixmap_clipped_regions *clipped_dst_regions;
-        int n_dst_region, i, j, k;
-        BoxRec box;
-        RegionRec region;
-
-        box.x1 = x;
-        box.y1 = y;
-        box.x2 = x + width;
-        box.y2 = y + height;
-        RegionInitBoxes(&region, &box, 1);
-        clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
-                                                             &region,
-                                                             &n_dst_region, 0,
-                                                             0, 0);
-        for (i = 0; i < n_dst_region; i++) {
-            int n_src_region;
-            glamor_pixmap_clipped_regions *clipped_src_regions;
-            BoxPtr current_boxes;
-            int n_current_boxes;
-
-            SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv,
-                                   clipped_dst_regions[i].block_idx);
-
-            if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
-                RegionTranslate(clipped_dst_regions[i].region,
-                                tile_x - x, tile_y - y);
-                DEBUGF("tiled a large src pixmap. %dx%d \n",
-                       tile->drawable.width, tile->drawable.height);
-                clipped_src_regions =
-                    glamor_compute_clipped_regions(src_pixmap_priv,
-                                                   clipped_dst_regions[i].
-                                                   region, &n_src_region, 1, 0,
-                                                   0);
-                DEBUGF("got %d src regions %d \n", n_src_region);
-                for (j = 0; j < n_src_region; j++) {
-
-                    SET_PIXMAP_FBO_CURRENT(src_pixmap_priv,
-                                           clipped_src_regions[j].block_idx);
-
-                    RegionTranslate(clipped_src_regions[j].region,
-                                    x - tile_x, y - tile_y);
-                    current_boxes = RegionRects(clipped_src_regions[j].region);
-                    n_current_boxes =
-                        RegionNumRects(clipped_src_regions[j].region);
-                    for (k = 0; k < n_current_boxes; k++) {
-                        DEBUGF
-                            ("Tile on %d %d %d %d dst block id %d tile block id %d tilex %d tiley %d\n",
-                             current_boxes[k].x1, current_boxes[k].y1,
-                             current_boxes[k].x2 - current_boxes[k].x1,
-                             current_boxes[k].y2 - current_boxes[k].y1,
-                             clipped_dst_regions[i].block_idx,
-                             clipped_src_regions[j].block_idx,
-                             (tile_x + (current_boxes[k].x1 - x)),
-                             tile_y + (current_boxes[k].y1 - y));
-
-                        _glamor_tile(pixmap, tile,
-                                     current_boxes[k].x1, current_boxes[k].y1,
-                                     current_boxes[k].x2 - current_boxes[k].x1,
-                                     current_boxes[k].y2 - current_boxes[k].y1,
-                                     (tile_x + (current_boxes[k].x1 - x)),
-                                     (tile_y + (current_boxes[k].y1 - y)));
-                    }
-
-                    RegionDestroy(clipped_src_regions[j].region);
-                }
-                free(clipped_src_regions);
-            }
-            else {
-                current_boxes = RegionRects(clipped_dst_regions[i].region);
-                n_current_boxes = RegionNumRects(clipped_dst_regions[i].region);
-                for (k = 0; k < n_current_boxes; k++) {
-                    _glamor_tile(pixmap, tile,
-                                 current_boxes[k].x1, current_boxes[k].y1,
-                                 current_boxes[k].x2 - current_boxes[k].x1,
-                                 current_boxes[k].y2 - current_boxes[k].y1,
-                                 (tile_x + (current_boxes[k].x1 - x)),
-                                 (tile_y + (current_boxes[k].y1 - y)));
-                }
-            }
-            RegionDestroy(clipped_dst_regions[i].region);
-        }
-        free(clipped_dst_regions);
-        RegionUninit(&region);
-    }
-    else
-        _glamor_tile(pixmap, tile, x, y, width, height, tile_x, tile_y);
-
-    glamor_set_alu(screen, GXcopy);
-    return TRUE;
- fail:
-    return FALSE;
-
-}
commit 18c09e60bf16b28060ade5d24110f2aa6bc19b57
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Mar 16 20:49:28 2014 -0700

    glamor: Replace glamor_solid_boxes and glamor_solid with GC using code
    
    This provides glamor_solid_boxes and glamor_solid using regular GC
    operations instead of calling directly to underlying rendering
    functions. This will allow the old rendering code to be removed.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 9dd06eb..30fcef1 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -11,7 +11,6 @@ libglamor_la_SOURCES = \
 	glamor_core.c \
 	glamor_dash.c \
 	glamor_debug.h \
-	glamor_fill.c \
 	glamor_font.c \
 	glamor_font.h \
 	glamor_glx.c \
@@ -46,6 +45,7 @@ libglamor_la_SOURCES = \
 	glamor_window.c\
 	glamor_fbo.c\
 	glamor_compositerects.c\
+	glamor_utils.c\
 	glamor_utils.h\
 	glamor.h
 
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 1ae0382..6891881 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -514,7 +514,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 
     glamor_init_vbo(screen);
     glamor_init_pixmap_fbo(screen);
-    glamor_init_solid_shader(screen);
     glamor_init_tile_shader(screen);
 #ifdef GLAMOR_TRAPEZOID_SHADER
     glamor_init_trapezoid_shader(screen);
@@ -547,7 +546,6 @@ glamor_release_screen_priv(ScreenPtr screen)
 #endif
     glamor_fini_vbo(screen);
     glamor_fini_pixmap_fbo(screen);
-    glamor_fini_solid_shader(screen);
     glamor_fini_tile_shader(screen);
 #ifdef GLAMOR_TRAPEZOID_SHADER
     glamor_fini_trapezoid_shader(screen);
diff --git a/glamor/glamor_fill.c b/glamor/glamor_fill.c
deleted file mode 100644
index 073904d..0000000
--- a/glamor/glamor_fill.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright © 2008 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Keith Packard makes no
- * representations about the suitability of this software for any purpose.  It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric at anholt.net>
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- */
-
-#include "glamor_priv.h"
-
-/** @file glamor_fill.c
- *
- * GC fill implementation, based loosely on fb_fill.c
- */
-
-/**
- * Fills the given rectangle of a drawable with the GC's fill style.
- */
-Bool
-glamor_fill(DrawablePtr drawable,
-            GCPtr gc, int x, int y, int width, int height, Bool fallback)
-{
-    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(drawable);
-    int off_x, off_y;
-    PixmapPtr sub_pixmap = NULL;
-    glamor_access_t sub_pixmap_access;
-    DrawablePtr saved_drawable = NULL;
-    int saved_x = x, saved_y = y;
-
-    glamor_get_drawable_deltas(drawable, dst_pixmap, &off_x, &off_y);
-
-    switch (gc->fillStyle) {
-    case FillSolid:
-        if (!glamor_solid(dst_pixmap,
-                          x + off_x,
-                          y + off_y,
-                          width, height, gc->alu, gc->planemask, gc->fgPixel))
-            goto fail;
-        break;
-    case FillStippled:
-    case FillOpaqueStippled:
-        if (!glamor_stipple(dst_pixmap,
-                            gc->stipple,
-                            x + off_x,
-                            y + off_y,
-                            width,
-                            height,
-                            gc->alu,
-                            gc->planemask,
-                            gc->fgPixel,
-                            gc->bgPixel, gc->patOrg.x, gc->patOrg.y))
-            goto fail;
-        break;
-    case FillTiled:
-        if (!glamor_tile(dst_pixmap,
-                         gc->tile.pixmap,
-                         x + off_x,
-                         y + off_y,
-                         width,
-                         height,
-                         gc->alu,
-                         gc->planemask,
-                         x - drawable->x - gc->patOrg.x,
-                         y - drawable->y - gc->patOrg.y))
-            goto fail;
-        break;
-    }
-    return TRUE;
-
- fail:
-    if (!fallback) {
-        if (glamor_ddx_fallback_check_pixmap(&dst_pixmap->drawable)
-            && glamor_ddx_fallback_check_gc(gc))
-            return FALSE;
-    }
-    /* Is it possible to set the access as WO? */
-
-    sub_pixmap_access = GLAMOR_ACCESS_RW;
-
-    sub_pixmap = glamor_get_sub_pixmap(dst_pixmap, x + off_x,
-                                       y + off_y, width, height,
-                                       sub_pixmap_access);
-
-    if (sub_pixmap != NULL) {
-        if (gc->fillStyle != FillSolid) {
-            gc->patOrg.x += (drawable->x - x);
-            gc->patOrg.y += (drawable->y - y);
-        }
-        saved_drawable = drawable;
-        drawable = &sub_pixmap->drawable;
-        saved_x = x;
-        saved_y = y;
-        x = 0;
-        y = 0;
-    }
-    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access_gc(gc)) {
-        fbFill(drawable, gc, x, y, width, height);
-    }
-    glamor_finish_access_gc(gc);
-    glamor_finish_access(drawable);
-
-    if (sub_pixmap != NULL) {
-        if (gc->fillStyle != FillSolid) {
-            gc->patOrg.x -= (saved_drawable->x - saved_x);
-            gc->patOrg.y -= (saved_drawable->y - saved_y);
-        }
-
-        x = saved_x;
-        y = saved_y;
-
-        glamor_put_sub_pixmap(sub_pixmap, dst_pixmap,
-                              x + off_x, y + off_y,
-                              width, height, sub_pixmap_access);
-    }
-
-    return TRUE;
-}
-
-void
-glamor_init_solid_shader(ScreenPtr screen)
-{
-    glamor_screen_private *glamor_priv;
-    const char *solid_vs =
-        "attribute vec4 v_position;"
-        "void main()\n"
-        "{\n"
-        "       gl_Position = v_position;\n"
-        "}\n";
-    const char *solid_fs =
-        GLAMOR_DEFAULT_PRECISION
-        "uniform vec4 color;\n"
-        "void main()\n"
-        "{\n"
-        "	gl_FragColor = color;\n"
-        "}\n";
-    GLint fs_prog, vs_prog;
-
-    glamor_priv = glamor_get_screen_private(screen);
-    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);
-    glAttachShader(glamor_priv->solid_prog, vs_prog);
-    glAttachShader(glamor_priv->solid_prog, fs_prog);
-
-    glBindAttribLocation(glamor_priv->solid_prog,
-                         GLAMOR_VERTEX_POS, "v_position");
-    glamor_link_glsl_prog(screen, glamor_priv->solid_prog, "solid");
-
-    glamor_priv->solid_color_uniform_location =
-        glGetUniformLocation(glamor_priv->solid_prog, "color");
-}
-
-void
-glamor_fini_solid_shader(ScreenPtr screen)
-{
-    glamor_screen_private *glamor_priv;
-
-    glamor_priv = glamor_get_screen_private(screen);
-    glamor_make_current(glamor_priv);
-    glDeleteProgram(glamor_priv->solid_prog);
-}
-
-static void
-_glamor_solid_boxes(PixmapPtr pixmap, BoxPtr box, int nbox, float *color)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    GLfloat xscale, yscale;
-    float stack_vertices[32];
-    float *vertices = stack_vertices;
-    int valid_nbox = ARRAY_SIZE(stack_vertices) / (4 * 2);
-
-    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
-
-    glamor_make_current(glamor_priv);
-    glUseProgram(glamor_priv->solid_prog);
-
-    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
-
-    pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
-
-    if (nbox > valid_nbox) {
-        int allocated_nbox;
-        float *new_vertices;
-
-        if (nbox > GLAMOR_COMPOSITE_VBO_VERT_CNT / 6)
-            allocated_nbox = GLAMOR_COMPOSITE_VBO_VERT_CNT / 6;
-        else
-            allocated_nbox = nbox;
-        new_vertices = malloc(allocated_nbox * 4 * 2 * sizeof(float));
-        if (new_vertices) {
-            vertices = new_vertices;
-            valid_nbox = allocated_nbox;
-        }
-    }
-
-    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                          GL_FALSE, 2 * sizeof(float), vertices);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-
-    while (nbox) {
-        int box_cnt, i;
-        float *next_box;
-
-        next_box = vertices;
-        box_cnt = nbox > valid_nbox ? valid_nbox : nbox;
-        for (i = 0; i < box_cnt; i++) {
-            glamor_set_normalize_vcoords(pixmap_priv, xscale, yscale,
-                                         box[i].x1, box[i].y1,
-                                         box[i].x2, box[i].y2,
-                                         glamor_priv->yInverted,
-                                         next_box);
-            next_box += 4 * 2;
-        }
-        if (box_cnt == 1)
-            glDrawArrays(GL_TRIANGLE_FAN, 0, box_cnt * 4);
-        else {
-            if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-                glDrawRangeElements(GL_TRIANGLES, 0, box_cnt * 4, box_cnt * 6,
-                                    GL_UNSIGNED_SHORT, NULL);
-            } else {
-                glDrawElements(GL_TRIANGLES, box_cnt * 6, GL_UNSIGNED_SHORT,
-                               NULL);
-            }
-        }
-        nbox -= box_cnt;
-        box += box_cnt;
-    }
-
-    if (vertices != stack_vertices)
-        free(vertices);
-
-    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glamor_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
-}
-
-/**
- * Fills the given rectangles of pixmap with an X pixel value.
- *
- * This is a helper used by other code after clipping and translation
- * of coordinates to a glamor backing pixmap.
- */
-Bool
-glamor_solid_boxes(PixmapPtr pixmap,
-                   BoxPtr box, int nbox, unsigned long fg_pixel)
-{
-    glamor_pixmap_private *pixmap_priv;
-    GLfloat color[4];
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return FALSE;
-
-    glamor_get_rgba_from_pixel(fg_pixel,
-                               &color[0],
-                               &color[1],
-                               &color[2], &color[3], format_for_pixmap(pixmap));
-
-    if (pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
-        RegionRec region;
-        int n_region;
-        glamor_pixmap_clipped_regions *clipped_regions;
-        int i;
-
-        RegionInitBoxes(&region, box, nbox);
-        clipped_regions =
-            glamor_compute_clipped_regions(pixmap_priv, &region, &n_region, 0,
-                                           0, 0);
-        for (i = 0; i < n_region; i++) {
-            BoxPtr inner_box;
-            int inner_nbox;
-
-            SET_PIXMAP_FBO_CURRENT(pixmap_priv, clipped_regions[i].block_idx);
-
-            inner_box = RegionRects(clipped_regions[i].region);
-            inner_nbox = RegionNumRects(clipped_regions[i].region);
-            _glamor_solid_boxes(pixmap, inner_box, inner_nbox, color);
-            RegionDestroy(clipped_regions[i].region);
-        }
-        free(clipped_regions);
-        RegionUninit(&region);
-    }
-    else
-        _glamor_solid_boxes(pixmap, box, nbox, color);
-
-    return TRUE;
-}
-
-/**
- * Fills a rectangle of a pixmap with an X pixel value.
- *
- * This is a helper used by other glamor code mostly for clearing of
- * buffers to 0.
- */
-Bool
-glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
-             unsigned char alu, unsigned long planemask, unsigned long fg_pixel)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    glamor_pixmap_private *pixmap_priv;
-    BoxRec box;
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return FALSE;
-
-    if (!glamor_set_planemask(pixmap, planemask)) {
-        glamor_fallback("Failedto set planemask  in glamor_solid.\n");
-        return FALSE;
-    }
-
-    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);
-            return FALSE;
-        }
-    }
-    box.x1 = x;
-    box.y1 = y;
-    box.x2 = x + width;
-    box.y2 = y + height;
-    glamor_solid_boxes(pixmap, &box, 1, fg_pixel);
-
-    glamor_set_alu(screen, GXcopy);
-
-    return TRUE;
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 129eaaa..187a9b5 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -216,10 +216,6 @@ typedef struct glamor_screen_private {
         fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT];
     unsigned long fbo_cache_watermark;
 
-    /* glamor_solid */
-    GLint solid_prog;
-    GLint solid_color_uniform_location;
-
     /* glamor point shader */
     glamor_program point_prog;
 
@@ -547,7 +543,7 @@ glamor_pixmap_hcnt(glamor_pixmap_private *priv)
     for (y = 0; y < glamor_pixmap_hcnt(priv); y++)      \
         for (x = 0; x < glamor_pixmap_wcnt(priv); x++)
 
-/* 
+/*
  * Pixmap dynamic status, used by dynamic upload feature.
  *
  * GLAMOR_NONE:  initial status, don't need to do anything.
@@ -672,7 +668,7 @@ int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv);
 void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *, int, int, int, int);
 
 /* nc means no check. caller must ensure this pixmap has valid fbo.
- * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly. 
+ * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly.
  * */
 void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv);
 
@@ -689,18 +685,6 @@ RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
 void
 glamor_track_stipple(GCPtr gc);
 
-/* glamor_fill.c */
-Bool glamor_fill(DrawablePtr drawable,
-                 GCPtr gc, int x, int y, int width, int height, Bool fallback);
-Bool glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
-                  unsigned char alu, unsigned long planemask,
-                  unsigned long fg_pixel);
-Bool glamor_solid_boxes(PixmapPtr pixmap,
-                        BoxPtr box, int nbox, unsigned long fg_pixel);
-
-void glamor_init_solid_shader(ScreenPtr screen);
-void glamor_fini_solid_shader(ScreenPtr screen);
-
 /* glamor_glyphs.c */
 Bool glamor_realize_glyph_caches(ScreenPtr screen);
 void glamor_glyphs_fini(ScreenPtr screen);
@@ -821,10 +805,10 @@ glamor_get_vbo_space(ScreenPtr screen, unsigned size, char **vbo_offset);
 void
 glamor_put_vbo_space(ScreenPtr screen);
 
-/** 
+/**
  * Download a pixmap's texture to cpu memory. If success,
  * One copy of current pixmap's texture will be put into
- * the pixmap->devPrivate.ptr. Will use pbo to map to 
+ * the pixmap->devPrivate.ptr. Will use pbo to map to
  * the pointer if possible.
  * The pixmap must be a gl texture pixmap. gl_fbo must be GLAMOR_FBO_NORMAL and
  * gl_tex must be 1. Used by glamor_prepare_access.
@@ -837,9 +821,9 @@ void *glamor_download_sub_pixmap_to_cpu(PixmapPtr pixmap, int x, int y, int w,
                                         glamor_access_t access);
 
 /**
- * Restore a pixmap's data which is downloaded by 
- * glamor_download_pixmap_to_cpu to its original 
- * gl texture. Used by glamor_finish_access. 
+ * Restore a pixmap's data which is downloaded by
+ * glamor_download_pixmap_to_cpu to its original
+ * gl texture. Used by glamor_finish_access.
  *
  * The pixmap must originally be a texture -- gl_fbo must be
  * GLAMOR_FBO_NORMAL.
@@ -1054,6 +1038,17 @@ void glamor_composite_rectangles(CARD8 op,
                                  xRenderColor *color,
                                  int num_rects, xRectangle *rects);
 
+/* glamor_util.c */
+void
+glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
+             unsigned char alu, unsigned long planemask,
+             unsigned long fg_pixel);
+
+void
+glamor_solid_boxes(PixmapPtr pixmap,
+                   BoxPtr box, int nbox, unsigned long fg_pixel);
+
+
 /* glamor_xv */
 typedef struct {
     uint32_t transform_index;
@@ -1080,10 +1075,10 @@ void glamor_fini_xv_shader(ScreenPtr screen);
 
 #include"glamor_utils.h"
 
-/* Dynamic pixmap upload to texture if needed. 
+/* Dynamic pixmap upload to texture if needed.
  * Sometimes, the target is a gl texture pixmap/picture,
  * but the source or mask is in cpu memory. In that case,
- * upload the source/mask to gl texture and then avoid 
+ * upload the source/mask to gl texture and then avoid
  * fallback the whole process to cpu. Most of the time,
  * this will increase performance obviously. */
 
diff --git a/glamor/glamor_trapezoid.c b/glamor/glamor_trapezoid.c
index 4aba469..4ad0672 100644
--- a/glamor/glamor_trapezoid.c
+++ b/glamor/glamor_trapezoid.c
@@ -1392,12 +1392,9 @@ _glamor_generate_trapezoid_with_shader(ScreenPtr screen, PicturePtr picture,
     }
 
     /* First, clear all to zero */
-    if (!glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width,
-                      pixmap_priv->base.pixmap->drawable.height,
-                      GXclear, 0xFFFFFFFF, 0)) {
-        DEBUGF("glamor_solid failed, fallback\n");
-        return FALSE;
-    }
+    glamor_solid(pixmap, 0, 0, pixmap_priv->base.pixmap->drawable.width,
+                 pixmap_priv->base.pixmap->drawable.height,
+                 GXclear, 0xFFFFFFFF, 0);
 
     glamor_make_current(glamor_priv);
 
diff --git a/glamor/glamor_utils.c b/glamor/glamor_utils.c
new file mode 100644
index 0000000..5459d79
--- /dev/null
+++ b/glamor/glamor_utils.c
@@ -0,0 +1,82 @@
+/*
+ * 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"
+
+void
+glamor_solid_boxes(PixmapPtr pixmap,
+                   BoxPtr box, int nbox, unsigned long fg_pixel)
+{
+    DrawablePtr drawable = &pixmap->drawable;
+    GCPtr gc;
+    xRectangle *rect;
+    int n;
+
+    rect = malloc(nbox * sizeof (xRectangle));
+    if (!rect)
+        return;
+    for (n = 0; n < nbox; n++) {
+        rect[n].x = box[n].x1;
+        rect[n].y = box[n].y1;
+        rect[n].width = box[n].x2 - box[n].x1;
+        rect[n].height = box[n].y2 - box[n].y1;
+    }
+
+    gc = GetScratchGC(drawable->depth, drawable->pScreen);
+    if (gc) {
+        ChangeGCVal vals[1];
+
+        vals[0].val = fg_pixel;
+        ChangeGC(NullClient, gc, GCForeground, vals);
+        ValidateGC(drawable, gc);
+        gc->ops->PolyFillRect(drawable, gc, nbox, rect);
+        FreeScratchGC(gc);
+    }
+    free(rect);
+}
+
+void
+glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
+             unsigned char alu, unsigned long planemask,
+             unsigned long fg_pixel)
+{
+    DrawablePtr drawable = &pixmap->drawable;
+    GCPtr gc;
+    ChangeGCVal vals[3];
+    xRectangle rect;
+
+    vals[0].val = alu;
+    vals[1].val = planemask;
+    vals[2].val = fg_pixel;
+    gc = GetScratchGC(drawable->depth, drawable->pScreen);
+    if (!gc)
+        return;
+    ChangeGC(NullClient, gc, GCFunction|GCPlaneMask|GCForeground, vals);
+    ValidateGC(drawable, gc);
+    rect.x = x;
+    rect.y = y;
+    rect.width = width;
+    rect.height = height;
+    gc->ops->PolyFillRect(drawable, gc, 1, &rect);
+    FreeScratchGC(gc);
+}
+
commit bd3b2c48f69a5169aefb261c041462271c69a07a
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Apr 3 14:22:52 2014 -0700

    glamor: Add accelerated stipple support
    
    This copies the stipple to a 8bpp pixmap and uses that to paint the
    texture from.
    
    v2: Create deep stipple pixmap without GLAMOR_CREATE_FBO_NO_FBO
    
    v3: Fix stipple origin sign (matches tiles now). Track changes
        to original stipple with damage. This isn't required by the
        X spec, but java appears to depend on it, so we'll just do it.
        When Glamor switches to 8bpp bitmaps, we'll be able to render
        directly from them and not need this anymore.
    
    v4: Review comments from Eric:
    
        * Remove stray whitespace change
        * Avoid "large" pixmap for stipple by using GLAMOR_CREATE_NO_LARGE
        * Wrap to 80 columns
    
    v5: Don't crash when stipple damage tracker is destroyed
    
        The stipple damage tracker is automatically destroyed when the
        associated stipple pixmap is destroyed. When this happens, just
        clear the pointer from the GC rather than calling
        glamor_invalidate_stipple; that function would call
        DamageUnregister on the now invalid stipple damage pointer and
        crash.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index 31cf3dc..bafc420 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -326,6 +326,58 @@ GCOps glamor_gc_ops = {
     .PushPixels = glamor_push_pixels,
 };
 
+/*
+ * When the stipple is changed or drawn to, invalidate any
+ * cached copy
+ */
+static void
+glamor_invalidate_stipple(GCPtr gc)
+{
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+    if (gc_priv->stipple) {
+        if (gc_priv->stipple_damage)
+            DamageUnregister(gc_priv->stipple_damage);
+        glamor_destroy_pixmap(gc_priv->stipple);
+        gc_priv->stipple = NULL;
+    }
+}
+
+static void
+glamor_stipple_damage_report(DamagePtr damage, RegionPtr region,
+                             void *closure)
+{
+    GCPtr       gc = closure;
+
+    glamor_invalidate_stipple(gc);
+}
+
+static void
+glamor_stipple_damage_destroy(DamagePtr damage, void *closure)
+{
+    GCPtr               gc = closure;
+    glamor_gc_private   *gc_priv = glamor_get_gc_private(gc);
+
+    gc_priv->stipple_damage = NULL;
+    glamor_invalidate_stipple(gc);
+}
+
+void
+glamor_track_stipple(GCPtr gc)
+{
+    if (gc->stipple) {
+        glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+        if (!gc_priv->stipple_damage)
+            gc_priv->stipple_damage = DamageCreate(glamor_stipple_damage_report,
+                                                   glamor_stipple_damage_destroy,
+                                                   DamageReportNonEmpty,
+                                                   TRUE, gc->pScreen, gc);
+        if (gc_priv->stipple_damage)
+            DamageRegister(&gc->stipple->drawable, gc_priv->stipple_damage);
+    }
+}
+
 /**
  * uxa_validate_gc() sets the ops to glamor's implementations, which may be
  * accelerated or may sync the card and fall back to fb.
@@ -396,6 +448,9 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
         changes &= ~GCTile;
     }
 
+    if (changes & GCStipple)
+        glamor_invalidate_stipple(gc);
+
     if (changes & GCStipple && gc->stipple) {
         /* We can't inline stipple handling like we do for GCTile because
          * it sets fbgc privates.
@@ -430,6 +485,9 @@ glamor_destroy_gc(GCPtr gc)
         glamor_destroy_pixmap(gc_priv->dash);
         gc_priv->dash = NULL;
     }
+    glamor_invalidate_stipple(gc);
+    if (gc_priv->stipple_damage)
+        DamageDestroy(gc_priv->stipple_damage);
     miDestroyGC(gc);
 }
 
@@ -453,6 +511,7 @@ glamor_create_gc(GCPtr gc)
     glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
 
     gc_priv->dash = NULL;
+    gc_priv->stipple = NULL;
     if (!fbCreateGC(gc))
         return FALSE;
 
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 6480eb6..129eaaa 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -567,6 +567,8 @@ typedef enum glamor_pixmap_status {
 
 typedef struct {
     PixmapPtr   dash;
+    PixmapPtr   stipple;
+    DamagePtr   stipple_damage;
 } glamor_gc_private;
 
 extern DevPrivateKeyRec glamor_gc_private_key;
@@ -684,6 +686,9 @@ Bool glamor_set_alu(ScreenPtr screen, unsigned char alu);
 Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 RegionPtr glamor_bitmap_to_region(PixmapPtr pixmap);
 
+void
+glamor_track_stipple(GCPtr gc);
+
 /* glamor_fill.c */
 Bool glamor_fill(DrawablePtr drawable,
                  GCPtr gc, int x, int y, int width, int height, Bool fallback);
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index f3d4477..1d0328f 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -51,42 +51,51 @@ static const glamor_facet glamor_fill_tile = {
     .use = use_tile,
 };
 
-#if 0
 static Bool
-use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog)
+use_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
 {
-    return glamor_set_stippled(pixmap, gc, prog->fg_uniform, prog->fill_offset_uniform, prog->fill_size_uniform);
+    return glamor_set_stippled(pixmap, gc, prog->fg_uniform,
+                               prog->fill_offset_uniform,
+                               prog->fill_size_uniform);
 }
 
 static const glamor_facet glamor_fill_stipple = {
     .name = "stipple",
-    .version = 130,
-    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + pos;\n";
-    .fs_exec = ("       if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
+    .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
+    .fs_exec = ("       float a = texture2D(sampler, fill_pos).w;\n"
+                "       if (a == 0.0)\n"
                 "               discard;\n"
-                "       gl_FragColor = fg;\n")
-    .locations = glamor_program_location_fg | glamor_program_location_fill
+                "       gl_FragColor = fg;\n"),
+    .locations = glamor_program_location_fg | glamor_program_location_fill,
     .use = use_stipple,
 };
 
+static Bool
+use_opaque_stipple(PixmapPtr pixmap, GCPtr gc, glamor_program *prog, void *arg)
+{
+    if (!use_stipple(pixmap, gc, prog, arg))
+        return FALSE;
+    glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
+    return TRUE;
+}
+
 static const glamor_facet glamor_fill_opaque_stipple = {
     .name = "opaque_stipple",
-    .version = 130,
-    .vs_exec =  "       fill_pos = fill_offset + primitive.xy + pos;\n";
-    .fs_exec = ("       if (texelFetch(sampler, ivec2(mod(fill_pos,fill_size)), 0).x == 0)\n"
+    .vs_exec =  "       fill_pos = (fill_offset + primitive.xy + pos) / fill_size;\n",
+    .fs_exec = ("       float a = texture2D(sampler, fill_pos).w;\n"
+                "       if (a == 0.0)\n"
                 "               gl_FragColor = bg;\n"
                 "       else\n"
                 "               gl_FragColor = fg;\n"),
-    .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill
+    .locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_fill,
     .use = use_opaque_stipple
 };
-#endif
 
 static const glamor_facet *glamor_facet_fill[4] = {
     &glamor_fill_solid,
     &glamor_fill_tile,
-    NULL,
-    NULL,
+    &glamor_fill_stipple,
+    &glamor_fill_opaque_stipple,
 };
 
 typedef struct {
diff --git a/glamor/glamor_transform.c b/glamor/glamor_transform.c
index d6ba564..c1df560 100644
--- a/glamor/glamor_transform.c
+++ b/glamor/glamor_transform.c
@@ -198,6 +198,64 @@ glamor_set_tiled(PixmapPtr      pixmap,
                               size_uniform);
 }
 
+static PixmapPtr
+glamor_get_stipple_pixmap(GCPtr gc)
+{
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+    ScreenPtr   screen = gc->pScreen;
+    PixmapPtr   bitmap;
+    PixmapPtr   pixmap;
+    GCPtr       scratch_gc;
+    ChangeGCVal changes[2];
+
+    if (gc_priv->stipple)
+        return gc_priv->stipple;
+
+    bitmap = gc->stipple;
+    if (!bitmap)
+        goto bail;
+
+    pixmap = glamor_create_pixmap(screen,
+                                  bitmap->drawable.width,
+                                  bitmap->drawable.height,
+                                  8, GLAMOR_CREATE_NO_LARGE);
+    if (!pixmap)
+        goto bail;
+
+    scratch_gc = GetScratchGC(8, screen);
+    if (!scratch_gc)
+        goto bail_pixmap;
+
+    changes[0].val = 0xff;
+    changes[1].val = 0x00;
+    if (ChangeGC(NullClient, scratch_gc,
+                 GCForeground|GCBackground, changes) != Success)
+        goto bail_gc;
+    ValidateGC(&pixmap->drawable, scratch_gc);
+
+    (*scratch_gc->ops->CopyPlane)(&bitmap->drawable,
+                                  &pixmap->drawable,
+                                  scratch_gc,
+                                  0, 0,
+                                  bitmap->drawable.width,
+                                  bitmap->drawable.height,
+                                  0, 0, 0x1);
+
+    FreeScratchGC(scratch_gc);
+    gc_priv->stipple = pixmap;
+
+    glamor_track_stipple(gc);
+
+    return pixmap;
+
+bail_gc:
+    FreeScratchGC(scratch_gc);
+bail_pixmap:
+    glamor_destroy_pixmap(pixmap);
+bail:
+    return NULL;
+}
+
 Bool
 glamor_set_stippled(PixmapPtr      pixmap,
                     GCPtr          gc,
@@ -205,11 +263,19 @@ glamor_set_stippled(PixmapPtr      pixmap,
                     GLint          offset_uniform,
                     GLint          size_uniform)
 {
-    if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
+    PixmapPtr   stipple;
+
+    stipple = glamor_get_stipple_pixmap(gc);
+    if (!stipple)
         return FALSE;
 
-    if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x, gc->patOrg.y, offset_uniform, size_uniform))
+    if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
         return FALSE;
 
-    return TRUE;
+    return glamor_set_texture(pixmap,
+                              stipple,
+                              -gc->patOrg.x,
+                              -gc->patOrg.y,
+                              offset_uniform,
+                              size_uniform);
 }
commit d18f5801c9a632dd4d9f8b7912491b6623e943d5
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Apr 2 14:07:20 2014 -0700

    glamor: Add glamor_program based 0-width dashed lines
    
    This makes sure the pixelization for dashed lines matches non-dashed
    lines, while also speeding them up.
    
    v2: Switch to glamor_make_current
    
    v3: Create dash pattern pixmap without GLAMOR_CREATE_FBO_NO_FBO
    
    v4: Adopt suggestions from Eric's review:
    
      - Drops power-of-two alignment of our line vertex data, simplifying
        the code.
    
      - Stops reading from the VBO.  While on keithp's and my machines the
        VBO is mapped cached, on many implementations it will be mapped WC,
        making those reads extremely expensive.
    
      - Style fixes (line wrapping, spaces around operators).
    
    v5: Adopt suggestions from Markus' review:
    
      - Use max when computing zero-width dashed line length.
    
        Don't open code max here.
    
      - Embed CoordModePrevious into VBO writing for dashed lines
    
        Instead of pre-computing the coord mode previous results, just
        embed this in the loop which fills the vertex buffer. Saves
        re-writing the request buffer, and shortens the code a bit
    
    v6: Export glamor_destroy_gc for UXA
    
        UXA needs to call glamor_destroy_gc from its GCFuncs, so export
        it.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 8fd6ec1..9dd06eb 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -9,6 +9,7 @@ libglamor_la_SOURCES = \
 	glamor_context.h \
 	glamor_copy.c \
 	glamor_core.c \
+	glamor_dash.c \
 	glamor_debug.h \
 	glamor_fill.c \
 	glamor_font.c \
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 3468b51..1ae0382 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -37,6 +37,7 @@
 
 DevPrivateKeyRec glamor_screen_private_key;
 DevPrivateKeyRec glamor_pixmap_private_key;
+DevPrivateKeyRec glamor_gc_private_key;
 
 /**
  * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@@ -346,7 +347,15 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         LogMessage(X_WARNING,
                    "glamor%d: Failed to allocate pixmap private\n",
                    screen->myNum);
-        goto fail;;
+        goto fail;
+    }
+
+    if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC,
+                               sizeof (glamor_gc_private))) {
+        LogMessage(X_WARNING,
+                   "glamor%d: Failed to allocate gc private\n",
+                   screen->myNum);
+        goto fail;
     }
 
     if (epoxy_is_desktop_gl())
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 77fa01e..2cdb1d4 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -321,6 +321,10 @@ extern _X_EXPORT int glamor_create_gc(GCPtr gc);
 extern _X_EXPORT void glamor_validate_gc(GCPtr gc, unsigned long changes,
                                          DrawablePtr drawable);
 
+extern _X_EXPORT void glamor_destroy_gc(GCPtr gc);
+
+#define HAS_GLAMOR_DESTROY_GC 1
+
 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);
 
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index ffb6eba..31cf3dc 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -409,14 +409,35 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
         fbValidateGC(gc, changes, drawable);
     }
 
+    if (changes & GCDashList) {
+        glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+        if (gc_priv->dash) {
+            glamor_destroy_pixmap(gc_priv->dash);
+            gc_priv->dash = NULL;
+        }
+    }
+
     gc->ops = &glamor_gc_ops;
 }
 
+void
+glamor_destroy_gc(GCPtr gc)
+{
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+    if (gc_priv->dash) {
+        glamor_destroy_pixmap(gc_priv->dash);
+        gc_priv->dash = NULL;
+    }
+    miDestroyGC(gc);
+}
+
 static GCFuncs glamor_gc_funcs = {
     glamor_validate_gc,
     miChangeGC,
     miCopyGC,
-    miDestroyGC,
+    glamor_destroy_gc,
     miChangeClip,
     miDestroyClip,
     miCopyClip
@@ -429,6 +450,9 @@ static GCFuncs glamor_gc_funcs = {
 int
 glamor_create_gc(GCPtr gc)
 {
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+
+    gc_priv->dash = NULL;
     if (!fbCreateGC(gc))
         return FALSE;
 
diff --git a/glamor/glamor_dash.c b/glamor/glamor_dash.c
new file mode 100644
index 0000000..e8f60fa
--- /dev/null
+++ b/glamor/glamor_dash.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_program.h"
+#include "glamor_transform.h"
+#include "glamor_transfer.h"
+#include "glamor_prepare.h"
+
+static const char dash_vs_vars[] =
+    "attribute vec3 primitive;\n"
+    "varying float dash_offset;\n";
+
+static const char dash_vs_exec[] =
+    "       dash_offset = primitive.z / dash_length;\n"
+    GLAMOR_POS(gl_Position, primitive.xy);
+
+static const char dash_fs_vars[] =
+    "varying float dash_offset;\n";
+
+static const char on_off_fs_exec[] =
+    "       float pattern = texture2D(dash, vec2(dash_offset, 0.5)).w;\n"
+    "       if (pattern == 0.0)\n"
+    "               discard;\n";
+
+/* XXX deal with stippled double dashed lines once we have stippling support */
+static const char double_fs_exec[] =
+    "       float pattern = texture2D(dash, vec2(dash_offset, 0.5)).w;\n"
+    "       if (pattern == 0.0)\n"
+    "               gl_FragColor = bg;\n"
+    "       else\n"
+    "               gl_FragColor = fg;\n";
+
+
+static const glamor_facet glamor_facet_on_off_dash_lines = {
+    .version = 130,
+    .name = "poly_lines_on_off_dash",
+    .vs_vars = dash_vs_vars,
+    .vs_exec = dash_vs_exec,
+    .fs_vars = dash_fs_vars,
+    .fs_exec = on_off_fs_exec,
+    .locations = glamor_program_location_dash,
+};
+
+static const glamor_facet glamor_facet_double_dash_lines = {
+    .version = 130,
+    .name = "poly_lines_double_dash",
+    .vs_vars = dash_vs_vars,
+    .vs_exec = dash_vs_exec,
+    .fs_vars = dash_fs_vars,
+    .fs_exec = double_fs_exec,
+    .locations = (glamor_program_location_dash|
+                  glamor_program_location_fg|
+                  glamor_program_location_bg),
+};
+
+static PixmapPtr
+glamor_get_dash_pixmap(GCPtr gc)
+{
+    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
+    ScreenPtr   screen = gc->pScreen;
+    PixmapPtr   pixmap;
+    int         offset;
+    int         d;
+    uint32_t    pixel;
+    GCPtr       scratch_gc;
+
+    if (gc_priv->dash)
+        return gc_priv->dash;
+
+    offset = 0;
+    for (d = 0; d < gc->numInDashList; d++)
+        offset += gc->dash[d];
+
+    pixmap = glamor_create_pixmap(screen, offset, 1, 8, 0);
+    if (!pixmap)
+        goto bail;
+
+    scratch_gc = GetScratchGC(8, screen);
+    if (!scratch_gc)
+        goto bail_pixmap;
+
+    pixel = 0xffffffff;
+    offset = 0;
+    for (d = 0; d < gc->numInDashList; d++) {
+        xRectangle      rect;
+        ChangeGCVal     changes;
+
+        changes.val = pixel;
+        (void) ChangeGC(NullClient, scratch_gc,
+                        GCForeground, &changes);
+        ValidateGC(&pixmap->drawable, scratch_gc);
+        rect.x = offset;
+        rect.y = 0;
+        rect.width = gc->dash[d];
+        rect.height = 1;
+        scratch_gc->ops->PolyFillRect (&pixmap->drawable, scratch_gc, 1, &rect);
+        offset += gc->dash[d];
+        pixel = ~pixel;
+    }
+    FreeScratchGC(scratch_gc);
+
+    gc_priv->dash = pixmap;
+    return pixmap;
+
+bail_pixmap:
+    glamor_destroy_pixmap(pixmap);
+bail:
+    return NULL;
+}
+
+static glamor_program *
+glamor_dash_setup(DrawablePtr drawable, GCPtr gc)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    PixmapPtr dash_pixmap;
+    glamor_pixmap_private *dash_priv;
+    glamor_program *prog;
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    if (gc->lineWidth != 0)
+        goto bail;
+
+    dash_pixmap = glamor_get_dash_pixmap(gc);
+    dash_priv = glamor_get_pixmap_private(pixmap);
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dash_priv))
+        goto bail;
+
+    glamor_make_current(glamor_priv);
+
+    switch (gc->lineStyle) {
+    case LineOnOffDash:
+        prog = glamor_use_program_fill(pixmap, gc,
+                                       &glamor_priv->on_off_dash_line_progs,
+                                       &glamor_facet_on_off_dash_lines);
+        if (!prog)
+            goto bail_ctx;
+        break;
+    case LineDoubleDash:
+        if (gc->fillStyle != FillSolid)
+            goto bail_ctx;
+
+        prog = &glamor_priv->double_dash_line_prog;
+
+        if (!prog->prog) {
+            if (!glamor_build_program(screen, prog,
+                                      &glamor_facet_double_dash_lines,
+                                      NULL))
+                goto bail_ctx;
+        }
+
+        if (!glamor_use_program(pixmap, gc, prog, NULL))
+            goto bail_ctx;
+
+        glamor_set_color(pixmap, gc->fgPixel, prog->fg_uniform);
+        glamor_set_color(pixmap, gc->bgPixel, prog->bg_uniform);
+        break;
+
+    default:
+        goto bail_ctx;
+    }
+
+
+    /* Set the dash pattern as texture 1 */
+
+    glActiveTexture(GL_TEXTURE1);
+    glBindTexture(GL_TEXTURE_2D, dash_priv->base.fbo->tex);
+    glUniform1i(prog->dash_uniform, 1);
+    glUniform1f(prog->dash_length_uniform, dash_pixmap->drawable.width);
+
+    return prog;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+bail:
+    return NULL;
+}
+
+static void
+glamor_dash_loop(DrawablePtr drawable, GCPtr gc, glamor_program *prog,
+                 int n, GLenum mode)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    int box_x, box_y;
+    int off_x, off_y;
+
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int nbox = RegionNumRects(gc->pCompositeClip);
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE,
+                                        prog->matrix_uniform, &off_x, &off_y);
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            glDrawArrays(mode, 0, n);
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+}
+
+static int
+glamor_line_length(short x1, short y1, short x2, short y2)
+{
+    return max(abs(x2 - x1), abs(y2 - y1));
+}
+
+Bool
+glamor_poly_lines_dash_gl(DrawablePtr drawable, GCPtr gc,
+                          int mode, int n, DDXPointPtr points)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_program *prog;
+    short *v;
+    char *vbo_offset;
+    int add_last;
+    int dash_pos;
+    int prev_x, prev_y;
+    int i;
+
+    if (n < 2)
+        return TRUE;
+
+    if (!(prog = glamor_dash_setup(drawable, gc)))
+        return FALSE;
+
+    add_last = 0;
+    if (gc->capStyle != CapNotLast)
+        add_last = 1;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(drawable->pScreen,
+                             (n + add_last) * 3 * sizeof (short),
+                             &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
+                          3 * sizeof (short), vbo_offset);
+
+    dash_pos = gc->dashOffset;
+    prev_x = prev_y = 0;
+    for (i = 0; i < n; i++) {
+        int this_x = points[i].x;
+        int this_y = points[i].y;
+        if (i) {
+            if (mode == CoordModePrevious) {
+                this_x += prev_x;
+                this_y += prev_y;
+            }
+            dash_pos += glamor_line_length(prev_x, prev_y,
+                                           this_x, this_y);
+        }
+        v[0] = prev_x = this_x;
+        v[1] = prev_y = this_y;
+        v[2] = dash_pos;
+        v += 3;
+    }
+
+    if (add_last) {
+        v[0] = prev_x + 1;
+        v[1] = prev_y;
+        v[2] = dash_pos + 1;
+    }
+
+    glamor_put_vbo_space(screen);
+
+    glamor_dash_loop(drawable, gc, prog, n + add_last, GL_LINE_STRIP);
+
+    return TRUE;
+}
+
+static short *
+glamor_add_segment(short *v, short x1, short y1, short x2, short y2,
+                   int dash_start, int dash_end)
+{
+    v[0] = x1;
+    v[1] = y1;
+    v[2] = dash_start;
+
+    v[3] = x2;
+    v[4] = y2;
+    v[5] = dash_end;
+    return v + 6;
+}
+
+Bool
+glamor_poly_segment_dash_gl(DrawablePtr drawable, GCPtr gc,
+                            int nseg, xSegment *segs)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_program *prog;
+    short *v;
+    char *vbo_offset;
+    int dash_start = gc->dashOffset;
+    int add_last;
+    int i;
+
+    if (!(prog = glamor_dash_setup(drawable, gc)))
+        return FALSE;
+
+    add_last = 0;
+    if (gc->capStyle != CapNotLast)
+        add_last = 1;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(drawable->pScreen,
+                             (nseg<<add_last) * 6 * sizeof (short),
+                             &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 3, GL_SHORT, GL_FALSE,
+                          3 * sizeof (short), vbo_offset);
+
+    for (i = 0; i < nseg; i++) {
+        int dash_end = dash_start + glamor_line_length(segs[i].x1, segs[i].y1,
+                                                       segs[i].x2, segs[i].y2);
+        v = glamor_add_segment(v,
+                               segs[i].x1, segs[i].y1,
+                               segs[i].x2, segs[i].y2,
+                               dash_start, dash_end);
+        if (add_last)
+            v = glamor_add_segment(v,
+                                   segs[i].x2, segs[i].y2,
+                                   segs[i].x2 + 1, segs[i].y2,
+                                   dash_end, dash_end + 1);
+    }
+
+    glamor_put_vbo_space(screen);
+
+    glamor_dash_loop(drawable, gc, prog, nseg << (1 + add_last), GL_LINES);
+
+    return TRUE;
+}
diff --git a/glamor/glamor_lines.c b/glamor/glamor_lines.c
index ca3cccf..e9a6195 100644
--- a/glamor/glamor_lines.c
+++ b/glamor/glamor_lines.c
@@ -33,8 +33,8 @@ static const glamor_facet glamor_facet_poly_lines = {
 };
 
 static Bool
-glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
-                     int mode, int n, DDXPointPtr points)
+glamor_poly_lines_solid_gl(DrawablePtr drawable, GCPtr gc,
+                           int mode, int n, DDXPointPtr points)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -51,12 +51,6 @@ glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    if (gc->lineWidth != 0)
-        goto bail;
-
-    if (gc->lineStyle != LineSolid)
-        goto bail;
-
     add_last = 0;
     if (gc->capStyle != CapNotLast)
         add_last = 1;
@@ -133,6 +127,28 @@ bail:
     return FALSE;
 }
 
+static Bool
+glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
+                     int mode, int n, DDXPointPtr points)
+{
+    if (gc->lineWidth != 0)
+        return FALSE;
+
+    switch (gc->lineStyle) {
+    case LineSolid:
+        return glamor_poly_lines_solid_gl(drawable, gc, mode, n, points);
+    case LineOnOffDash:
+        return glamor_poly_lines_dash_gl(drawable, gc, mode, n, points);
+    case LineDoubleDash:
+        if (gc->fillStyle == FillTiled)
+            return glamor_poly_lines_solid_gl(drawable, gc, mode, n, points);
+        else
+            return glamor_poly_lines_dash_gl(drawable, gc, mode, n, points);
+    default:
+        return FALSE;
+    }
+}
+
 static void
 glamor_poly_lines_bail(DrawablePtr drawable, GCPtr gc,
                        int mode, int n, DDXPointPtr points)
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 07e1b89..6480eb6 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -247,6 +247,10 @@ typedef struct glamor_screen_private {
     /* glamor segment shaders */
     glamor_program_fill poly_segment_program;
 
+    /*  glamor dash line shader */
+    glamor_program_fill on_off_dash_line_progs;
+    glamor_program      double_dash_line_prog;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -559,6 +563,13 @@ typedef enum glamor_pixmap_status {
     GLAMOR_UPLOAD_FAILED
 } glamor_pixmap_status_t;
 
+/* GC private structure. Currently holds only any computed dash pixmap */
+
+typedef struct {
+    PixmapPtr   dash;
+} glamor_gc_private;
+
+extern DevPrivateKeyRec glamor_gc_private_key;
 extern DevPrivateKeyRec glamor_screen_private_key;
 extern DevPrivateKeyRec glamor_pixmap_private_key;
 
@@ -591,6 +602,12 @@ glamor_get_pixmap_private(PixmapPtr pixmap)
 
 void glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv);
 
+static inline glamor_gc_private *
+glamor_get_gc_private(GCPtr gc)
+{
+    return dixLookupPrivate(&gc->devPrivates, &glamor_gc_private_key);
+}
+
 /**
  * Returns TRUE if the given planemask covers all the significant bits in the
  * pixel values for pDrawable.
@@ -969,7 +986,17 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 void
 glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
                  unsigned int format, unsigned long planeMask, char *d);
-/*  glamor_lines.c */
+
+/* glamor_dash.c */
+Bool
+glamor_poly_lines_dash_gl(DrawablePtr drawable, GCPtr gc,
+                          int mode, int n, DDXPointPtr points);
+
+Bool
+glamor_poly_segment_dash_gl(DrawablePtr drawable, GCPtr gc,
+                            int nseg, xSegment *segs);
+
+/* glamor_lines.c */
 void
 glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
                   int mode, int n, DDXPointPtr points);
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index 6ee6580..f3d4477 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -122,6 +122,11 @@ static glamor_location_var location_vars[] = {
         .fs_vars = ("uniform uvec4 bitplane;\n"
                     "uniform vec4 bitmul;\n"),
     },
+    {
+        .location = glamor_program_location_dash,
+        .vs_vars = "uniform float dash_length;\n",
+        .fs_vars = "uniform sampler2D dash;\n",
+    },
 };
 
 #define NUM_LOCATION_VARS       (sizeof location_vars / sizeof location_vars[0])
@@ -326,6 +331,8 @@ glamor_build_program(ScreenPtr          screen,
     prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
     prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane");
     prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
+    prog->dash_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash");
+    prog->dash_length_uniform = glamor_get_uniform(prog, glamor_program_location_dash, "dash_length");
 
     if (glGetError() != GL_NO_ERROR)
         goto fail;
diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
index 118f978..56ba03a 100644
--- a/glamor/glamor_program.h
+++ b/glamor/glamor_program.h
@@ -30,6 +30,7 @@ typedef enum {
     glamor_program_location_fill = 4,
     glamor_program_location_font = 8,
     glamor_program_location_bitplane = 16,
+    glamor_program_location_dash = 32,
 } glamor_program_location;
 
 typedef enum {
@@ -64,6 +65,8 @@ struct _glamor_program {
     GLint                       font_uniform;
     GLint                       bitplane_uniform;
     GLint                       bitmul_uniform;
+    GLint                       dash_uniform;
+    GLint                       dash_length_uniform;
     glamor_program_location     locations;
     glamor_program_flag         flags;
     glamor_use                  prim_use;
diff --git a/glamor/glamor_segs.c b/glamor/glamor_segs.c
index 0168d05..ff0daef 100644
--- a/glamor/glamor_segs.c
+++ b/glamor/glamor_segs.c
@@ -33,8 +33,8 @@ static const glamor_facet glamor_facet_poly_segment = {
 };
 
 static Bool
-glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
-                       int nseg, xSegment *segs)
+glamor_poly_segment_solid_gl(DrawablePtr drawable, GCPtr gc,
+                             int nseg, xSegment *segs)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -51,12 +51,6 @@ glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
         goto bail;
 
-    if (gc->lineWidth != 0)
-        goto bail;
-
-    if (gc->lineStyle != LineSolid)
-        goto bail;
-
     add_last = 0;
     if (gc->capStyle != CapNotLast)
         add_last = 1;
@@ -125,6 +119,28 @@ bail:
     return FALSE;
 }
 
+static Bool
+glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
+                       int nseg, xSegment *segs)
+{
+    if (gc->lineWidth != 0)
+        return FALSE;
+
+    switch (gc->lineStyle) {
+    case LineSolid:
+        return glamor_poly_segment_solid_gl(drawable, gc, nseg, segs);
+    case LineOnOffDash:
+        return glamor_poly_segment_dash_gl(drawable, gc, nseg, segs);
+    case LineDoubleDash:
+        if (gc->fillStyle == FillTiled)
+            return glamor_poly_segment_solid_gl(drawable, gc, nseg, segs);
+        else
+            return glamor_poly_segment_dash_gl(drawable, gc, nseg, segs);
+    default:
+        return FALSE;
+    }
+}
+
 static void
 glamor_poly_segment_bail(DrawablePtr drawable, GCPtr gc,
                          int nseg, xSegment *segs)
@@ -143,7 +159,6 @@ glamor_poly_segment_bail(DrawablePtr drawable, GCPtr gc,
         miPolySegment(drawable, gc, nseg, segs);
 }
 
-
 void
 glamor_poly_segment(DrawablePtr drawable, GCPtr gc,
                     int nseg, xSegment *segs)
commit dc9fa9080a1cb994b4e54a341d2245f442dac576
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Mar 23 20:59:02 2014 -0700

    glamor: Use glamor_program and GL_LINES for 0-width lines
    
    GL lines are nearly X compliant; you just need to fill in the last
    pixel when the client hasn't requested CapNotLast.
    
    v2: switch to glamor_make_current
    
    v3: use miPolylines instead of custom glamor fallback path. Wrap
        code to 80 columns.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index c0d82d6..8fd6ec1 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -15,9 +15,9 @@ libglamor_la_SOURCES = \
 	glamor_font.h \
 	glamor_glx.c \
 	glamor_glyphs.c \
-	glamor_polylines.c \
-	glamor_segment.c \
 	glamor_image.c \
+	glamor_lines.c \
+	glamor_segs.c \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_prepare.c \
diff --git a/glamor/glamor_lines.c b/glamor/glamor_lines.c
new file mode 100644
index 0000000..ca3cccf
--- /dev/null
+++ b/glamor/glamor_lines.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_program.h"
+#include "glamor_transform.h"
+#include "glamor_prepare.h"
+
+static const glamor_facet glamor_facet_poly_lines = {
+    .name = "poly_lines",
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = ("       vec2 pos = vec2(0.0,0.0);\n"
+                GLAMOR_POS(gl_Position, primitive.xy)),
+};
+
+static Bool
+glamor_poly_lines_gl(DrawablePtr drawable, GCPtr gc,
+                     int mode, int n, DDXPointPtr points)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    glamor_program *prog;
+    int off_x, off_y;
+    DDXPointPtr v;
+    char *vbo_offset;
+    int box_x, box_y;
+    int add_last;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    if (gc->lineWidth != 0)
+        goto bail;
+
+    if (gc->lineStyle != LineSolid)
+        goto bail;
+
+    add_last = 0;
+    if (gc->capStyle != CapNotLast)
+        add_last = 1;
+
+    if (n < 2)
+        return TRUE;
+
+    glamor_make_current(glamor_priv);
+
+    prog = glamor_use_program_fill(pixmap, gc,
+                                   &glamor_priv->poly_line_program,
+                                   &glamor_facet_poly_lines);
+
+    if (!prog)
+        goto bail_ctx;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(drawable->pScreen,
+                             (n + add_last) * sizeof (DDXPointRec),
+                             &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
+                          sizeof (DDXPointRec), vbo_offset);
+
+    if (mode == CoordModePrevious) {
+        int i;
+        DDXPointRec here = { 0, 0 };
+
+        for (i = 0; i < n; i++) {
+            here.x += points[i].x;
+            here.y += points[i].y;
+            v[i] = here;
+        }
+    } else {
+        memcpy(v, points, n * sizeof (DDXPointRec));
+    }
+
+    if (add_last) {
+        v[n].x = v[n-1].x + 1;
+        v[n].y = v[n-1].y;
+    }
+
+    glamor_put_vbo_space(screen);
+
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int nbox = RegionNumRects(gc->pCompositeClip);
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE,
+                                        prog->matrix_uniform, &off_x, &off_y);
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            glDrawArrays(GL_LINE_STRIP, 0, n + add_last);
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    return TRUE;
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+bail:
+    return FALSE;
+}
+
+static void
+glamor_poly_lines_bail(DrawablePtr drawable, GCPtr gc,
+                       int mode, int n, DDXPointPtr points)
+{
+    glamor_fallback("to %p (%c)\n", drawable,
+                    glamor_get_drawable_location(drawable));
+
+    miPolylines(drawable, gc, mode, n, points);
+}
+
+void
+glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
+                  int mode, int n, DDXPointPtr points)
+{
+    if (glamor_poly_lines_gl(drawable, gc, mode, n, points))
+        return;
+    glamor_poly_lines_bail(drawable, gc, mode, n, points);
+}
+
+Bool
+glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
+                     int mode, int n, DDXPointPtr points)
+{
+    if (glamor_poly_lines_gl(drawable, gc, mode, n, points))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) &&
+        glamor_ddx_fallback_check_gc(gc))
+    {
+        return FALSE;
+    }
+
+    glamor_poly_lines_bail(drawable, gc, mode, n, points);
+    return TRUE;
+}
+
diff --git a/glamor/glamor_polylines.c b/glamor/glamor_polylines.c
deleted file mode 100644
index 1adf45d..0000000
--- a/glamor/glamor_polylines.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright © 2009 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric at anholt.net>
- *
- */
-
-#include "glamor_priv.h"
-
-/** @file glamor_polylines.c
- *
- * GC PolyFillRect implementation, taken straight from fb_fill.c
- */
-
-/**
- * glamor_poly_lines() checks if it can accelerate the lines as a group of
- * horizontal or vertical lines (rectangles), and uses existing rectangle fill
- * acceleration if so.
- */
-static Bool
-_glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
-                   DDXPointPtr points, Bool fallback)
-{
-    xRectangle *rects;
-    int x1, x2, y1, y2;
-    int i;
-
-    /* Don't try to do wide lines or non-solid fill style. */
-    if (gc->lineWidth != 0) {
-        /* This ends up in miSetSpans, which is accelerated as well as we
-         * can hope X wide lines will be.
-         */
-        goto fail;
-    }
-
-    if (gc->lineStyle != LineSolid) {
-        glamor_fallback("non-solid fill line style %d\n", gc->lineStyle);
-        goto fail;
-    }
-    rects = malloc(sizeof(xRectangle) * (n - 1));
-    x1 = points[0].x;
-    y1 = points[0].y;
-    /* If we have any non-horizontal/vertical, fall back. */
-    for (i = 0; i < n - 1; i++) {
-        if (mode == CoordModePrevious) {
-            x2 = x1 + points[i + 1].x;
-            y2 = y1 + points[i + 1].y;
-        }
-        else {
-            x2 = points[i + 1].x;
-            y2 = points[i + 1].y;
-        }
-        if (x1 != x2 && y1 != y2) {
-            free(rects);
-            glamor_fallback("stub diagonal poly_line\n");
-            goto fail;
-        }
-        if (x1 < x2) {
-            rects[i].x = x1;
-            rects[i].width = x2 - x1 + 1;
-        }
-        else {
-            rects[i].x = x2;
-            rects[i].width = x1 - x2 + 1;
-        }
-        if (y1 < y2) {
-            rects[i].y = y1;
-            rects[i].height = y2 - y1 + 1;
-        }
-        else {
-            rects[i].y = y2;
-            rects[i].height = y1 - y2 + 1;
-        }
-
-        x1 = x2;
-        y1 = y2;
-    }
-    gc->ops->PolyFillRect(drawable, gc, n - 1, rects);
-    free(rects);
-    return TRUE;
-
- fail:
-    if (!fallback && glamor_ddx_fallback_check_pixmap(drawable)
-        && glamor_ddx_fallback_check_gc(gc))
-        return FALSE;
-
-    switch (gc->lineStyle) {
-    case LineSolid:
-        if (gc->lineWidth == 0)
-            miZeroLine(drawable, gc, mode, n, points);
-        else
-            miWideLine(drawable, gc, mode, n, points);
-        break;
-    case LineOnOffDash:
-    case LineDoubleDash:
-        miWideDash(drawable, gc, mode, n, points);
-        break;
-    }
-
-    return TRUE;
-}
-
-void
-glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
-                  DDXPointPtr points)
-{
-    _glamor_poly_lines(drawable, gc, mode, n, points, TRUE);
-}
-
-Bool
-glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc, int mode, int n,
-                     DDXPointPtr points)
-{
-    return _glamor_poly_lines(drawable, gc, mode, n, points, FALSE);
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 1ae4e94..07e1b89 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -241,6 +241,12 @@ typedef struct glamor_screen_private {
     glamor_program      copy_area_prog;
     glamor_program      copy_plane_prog;
 
+    /* glamor line shader */
+    glamor_program_fill poly_line_program;
+
+    /* glamor segment shaders */
+    glamor_program_fill poly_segment_program;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -683,10 +689,6 @@ void glamor_glyphs(CARD8 op,
                    INT16 xSrc,
                    INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs);
 
-/* glamor_polylines.c */
-void glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
-                       DDXPointPtr points);
-
 /* glamor_render.c */
 Bool glamor_composite_clipped_region(CARD8 op,
                                      PicturePtr source,
@@ -967,6 +969,15 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 void
 glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
                  unsigned int format, unsigned long planeMask, char *d);
+/*  glamor_lines.c */
+void
+glamor_poly_lines(DrawablePtr drawable, GCPtr gc,
+                  int mode, int n, DDXPointPtr points);
+
+/*  glamor_segs.c */
+void
+glamor_poly_segment(DrawablePtr drawable, GCPtr gc,
+                    int nseg, xSegment *segs);
 
 /* glamor_copy.c */
 void
@@ -1006,12 +1017,6 @@ void glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
 void glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
                        DDXPointPtr ppt);
 
-void glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
-                         xSegment *pSeg);
-
-void glamor_poly_line(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
-                      DDXPointPtr ppt);
-
 void glamor_composite_rectangles(CARD8 op,
                                  PicturePtr dst,
                                  xRenderColor *color,
diff --git a/glamor/glamor_segment.c b/glamor/glamor_segment.c
deleted file mode 100644
index 53f7da0..0000000
--- a/glamor/glamor_segment.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright © 2014 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-#include "glamor_priv.h"
-
-Bool
-glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc, int nseg,
-                       xSegment *seg)
-{
-    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)
-{
-    miPolySegment(drawable, gc, nseg, seg);
-}
diff --git a/glamor/glamor_segs.c b/glamor/glamor_segs.c
new file mode 100644
index 0000000..0168d05
--- /dev/null
+++ b/glamor/glamor_segs.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_program.h"
+#include "glamor_transform.h"
+#include "glamor_prepare.h"
+
+static const glamor_facet glamor_facet_poly_segment = {
+    .name = "poly_segment",
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = ("       vec2 pos = vec2(0.0,0.0);\n"
+                GLAMOR_POS(gl_Position, primitive.xy)),
+};
+
+static Bool
+glamor_poly_segment_gl(DrawablePtr drawable, GCPtr gc,
+                       int nseg, xSegment *segs)
+{
+    ScreenPtr screen = drawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    glamor_pixmap_private *pixmap_priv;
+    glamor_program *prog;
+    int off_x, off_y;
+    xSegment *v;
+    char *vbo_offset;
+    int box_x, box_y;
+    int add_last;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+        goto bail;
+
+    if (gc->lineWidth != 0)
+        goto bail;
+
+    if (gc->lineStyle != LineSolid)
+        goto bail;
+
+    add_last = 0;
+    if (gc->capStyle != CapNotLast)
+        add_last = 1;
+
+    glamor_make_current(glamor_priv);
+
+    prog = glamor_use_program_fill(pixmap, gc,
+                                   &glamor_priv->poly_segment_program,
+                                   &glamor_facet_poly_segment);
+
+    if (!prog)
+        goto bail_ctx;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(drawable->pScreen,
+                             (nseg << add_last) * sizeof (xSegment),
+                             &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
+                          sizeof(DDXPointRec), vbo_offset);
+
+    if (add_last) {
+        int i, j;
+        for (i = 0, j=0; i < nseg; i++) {
+            v[j++] = segs[i];
+            v[j].x1 = segs[i].x2;
+            v[j].y1 = segs[i].y2;
+            v[j].x2 = segs[i].x2+1;
+            v[j].y2 = segs[i].y2;
+            j++;
+        }
+    } else
+        memcpy(v, segs, nseg * sizeof (xSegment));
+
+    glamor_put_vbo_space(screen);
+
+    glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        int nbox = RegionNumRects(gc->pCompositeClip);
+        BoxPtr box = RegionRects(gc->pCompositeClip);
+
+        glamor_set_destination_drawable(drawable, box_x, box_y, TRUE, TRUE,
+                                        prog->matrix_uniform, &off_x, &off_y);
+
+        while (nbox--) {
+            glScissor(box->x1 + off_x,
+                      box->y1 + off_y,
+                      box->x2 - box->x1,
+                      box->y2 - box->y1);
+            box++;
+            glDrawArrays(GL_LINES, 0, nseg << (1 + add_last));
+        }
+    }
+
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_COLOR_LOGIC_OP);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    return TRUE;
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+bail:
+    return FALSE;
+}
+
+static void
+glamor_poly_segment_bail(DrawablePtr drawable, GCPtr gc,
+                         int nseg, xSegment *segs)
+{
+    glamor_fallback("to %p (%c)\n", drawable,
+                    glamor_get_drawable_location(drawable));
+
+    if (gc->lineWidth == 0) {
+        if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+            glamor_prepare_access_gc(gc)) {
+            fbPolySegment(drawable, gc, nseg, segs);
+        }
+        glamor_finish_access_gc(gc);
+        glamor_finish_access(drawable);
+    } else
+        miPolySegment(drawable, gc, nseg, segs);
+}
+
+
+void
+glamor_poly_segment(DrawablePtr drawable, GCPtr gc,
+                    int nseg, xSegment *segs)
+{
+    if (glamor_poly_segment_gl(drawable, gc, nseg, segs))
+        return;
+
+    glamor_poly_segment_bail(drawable, gc, nseg, segs);
+}
+
+Bool
+glamor_poly_segment_nf(DrawablePtr drawable, GCPtr gc,
+                       int nseg, xSegment *segs)
+{
+    if (glamor_poly_segment_gl(drawable, gc, nseg, segs))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) &&
+        glamor_ddx_fallback_check_gc(gc))
+    {
+        return FALSE;
+    }
+
+    glamor_poly_segment_bail(drawable, gc, nseg, segs);
+    return TRUE;
+}
+
commit 51075ebd37dca8d17c42425fb756ad3090e157c4
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 18:03:07 2014 -0700

    glamor: Use glamor_program for glamor_push_pixels
    
    This uses the same shaders as glamor_poly_glyph_blt.
    
    v2: Wrap some long lines (changes by anholt).
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor_glyphblt.c b/glamor/glamor_glyphblt.c
index 1c511ff..73b1df5 100644
--- a/glamor/glamor_glyphblt.c
+++ b/glamor/glamor_glyphblt.c
@@ -56,7 +56,8 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
 
     glamor_make_current(glamor_priv);
 
-    prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->poly_glyph_blt_progs,
+    prog = glamor_use_program_fill(pixmap, gc,
+                                   &glamor_priv->poly_glyph_blt_progs,
                                    &glamor_facet_poly_glyph_blt);
     if (!prog)
         goto bail_ctx;
@@ -74,7 +75,8 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
         int off_x, off_y;
         char *vbo_offset;
 
-        glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE, prog->matrix_uniform, &off_x, &off_y);
+        glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE,
+                                        prog->matrix_uniform, &off_x, &off_y);
 
         max_points = 500;
         num_points = 0;
@@ -105,10 +107,12 @@ glamor_poly_glyph_blt_gl(DrawablePtr drawable, GCPtr gc,
 
                         if (!num_points) {
                             points = glamor_get_vbo_space(screen,
-                                                          max_points * (2 * sizeof (INT16)),
+                                                          max_points *
+                                                          (2 * sizeof (INT16)),
                                                           &vbo_offset);
 
-                            glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
+                            glVertexAttribPointer(GLAMOR_VERTEX_POS,
+                                                  2, GL_SHORT,
                                                   GL_FALSE, 0, vbo_offset);
                         }
 
@@ -149,7 +153,8 @@ glamor_poly_glyph_blt(DrawablePtr drawable, GCPtr gc,
                       int start_x, int y, unsigned int nglyph,
                       CharInfoPtr *ppci, void *pglyph_base)
 {
-    if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
+    if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci,
+                                 pglyph_base))
         return;
     miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
                    ppci, pglyph_base);
@@ -160,10 +165,13 @@ glamor_poly_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
                          int start_x, int y, unsigned int nglyph,
                          CharInfoPtr *ppci, void *pglyph_base)
 {
-    if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci, pglyph_base))
+    if (glamor_poly_glyph_blt_gl(drawable, gc, start_x, y, nglyph, ppci,
+                                 pglyph_base))
         return TRUE;
-    if (glamor_ddx_fallback_check_pixmap(drawable) && glamor_ddx_fallback_check_gc(gc))
+    if (glamor_ddx_fallback_check_pixmap(drawable) &&
+        glamor_ddx_fallback_check_gc(gc)) {
         return FALSE;
+    }
     miPolyGlyphBlt(drawable, gc, start_x, y, nglyph,
                    ppci, pglyph_base);
     return TRUE;
@@ -179,8 +187,8 @@ glamor_image_glyph_blt_nf(DrawablePtr drawable, GCPtr gc,
 }
 
 static Bool
-glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
-                          DrawablePtr drawable, int w, int h, int x, int y)
+glamor_push_pixels_gl(GCPtr gc, PixmapPtr bitmap,
+                      DrawablePtr drawable, int w, int h, int x, int y)
 {
     ScreenPtr screen = drawable->pScreen;
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
@@ -188,65 +196,40 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
     glamor_pixmap_private *pixmap_priv;
     uint8_t *bitmap_data = bitmap->devPrivate.ptr;
     int bitmap_stride = bitmap->devKind;
-    int off_x, off_y;
+    glamor_program *prog;
+    RegionPtr clip = gc->pCompositeClip;
+    int box_x, box_y;
     int yy, xx;
-    GLfloat xscale, yscale;
-    float color[4];
-    unsigned long fg_pixel = gc->fgPixel;
-    float *points, *next_point;
-    int num_points = 0;
+    int num_points;
+    INT16 *points = NULL;
     char *vbo_offset;
-    RegionPtr clip;
 
     if (w * h > MAXINT / (2 * sizeof(float)))
-        return FALSE;
-
-    if (gc->fillStyle != FillSolid) {
-        glamor_fallback("gc fillstyle not solid\n");
-        return FALSE;
-    }
+        goto bail;
 
     pixmap_priv = glamor_get_pixmap_private(pixmap);
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
-        return FALSE;
+        goto bail;
 
     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);
-            return FALSE;
-        }
-    }
-
-    if (!glamor_set_planemask(pixmap, gc->planemask)) {
-        glamor_fallback("Failed to set planemask in %s.\n", __FUNCTION__);
-        return FALSE;
-    }
-
-    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
-
-    glamor_set_destination_pixmap_priv_nc(pixmap_priv);
-    pixmap_priv_get_dest_scale(pixmap_priv, &xscale, &yscale);
 
-    glUseProgram(glamor_priv->solid_prog);
+    prog = glamor_use_program_fill(pixmap, gc,
+                                   &glamor_priv->poly_glyph_blt_progs,
+                                   &glamor_facet_poly_glyph_blt);
+    if (!prog)
+        goto bail_ctx;
 
-    glamor_get_rgba_from_pixel(fg_pixel,
-                               &color[0], &color[1], &color[2], &color[3],
-                               format_for_pixmap(pixmap));
-    glUniform4fv(glamor_priv->solid_color_uniform_location, 1, color);
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
 
-    points = glamor_get_vbo_space(screen, w * h * sizeof(float) * 2,
+    points = glamor_get_vbo_space(screen, w * h * sizeof(INT16) * 2,
                                   &vbo_offset);
-    next_point = points;
-
-    clip = fbGetCompositeClip(gc);
+    num_points = 0;
 
     /* Note that because fb sets miTranslate in the GC, our incoming X
      * and Y are in screen coordinate space (same for spans, but not
      * other operations).
      */
+
     for (yy = 0; yy < h; yy++) {
         uint8_t *bitmap_row = bitmap_data + yy * bitmap_stride;
         for (xx = 0; xx < w; xx++) {
@@ -255,63 +238,58 @@ glamor_push_pixels_points(GCPtr gc, PixmapPtr bitmap,
                                     x + xx,
                                     y + yy,
                                     NULL)) {
-                next_point[0] = v_from_x_coord_x(xscale, x + xx + off_x + 0.5);
-                if (glamor_priv->yInverted)
-                    next_point[1] = v_from_x_coord_y_inverted(yscale, y + yy + off_y + 0.5);
-                else
-                    next_point[1] = v_from_x_coord_y(yscale, y + yy + off_y + 0.5);
-
-                next_point += 2;
+                *points++ = x + xx;
+                *points++ = y + yy;
                 num_points++;
             }
         }
     }
-    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                          GL_FALSE, 2 * sizeof(float),
-                          vbo_offset);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT,
+                          GL_FALSE, 0, vbo_offset);
 
     glamor_put_vbo_space(screen);
 
-    glDrawArrays(GL_POINTS, 0, num_points);
-
-    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-
-    return TRUE;
-}
-
-static Bool
-_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
-                    DrawablePtr pDrawable, int w, int h, int x, int y,
-                    Bool fallback)
-{
-    glamor_pixmap_private *pixmap_priv;
-
-    if (!fallback && glamor_ddx_fallback_check_pixmap(pDrawable)
-        && glamor_ddx_fallback_check_pixmap(&pBitmap->drawable)
-        && glamor_ddx_fallback_check_gc(pGC))
-        return FALSE;
+    glamor_pixmap_loop(pixmap_priv, box_x, box_y) {
+        glamor_set_destination_drawable(drawable, box_x, box_y, FALSE, TRUE,
+                                        prog->matrix_uniform, NULL, NULL);
 
-    pixmap_priv = glamor_get_pixmap_private(pBitmap);
-    if (pixmap_priv->type == GLAMOR_MEMORY) {
-        if (glamor_push_pixels_points(pGC, pBitmap, pDrawable, w, h, x, y))
-            return TRUE;
+        glDrawArrays(GL_POINTS, 0, num_points);
     }
 
-    miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
+    glDisable(GL_COLOR_LOGIC_OP);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
     return TRUE;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+bail:
+    return FALSE;
 }
 
 void
 glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
                    DrawablePtr pDrawable, int w, int h, int x, int y)
 {
-    _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, TRUE);
+    if (glamor_push_pixels_gl(pGC, pBitmap, pDrawable, w, h, x, y))
+        return;
+
+    miPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
 }
 
 Bool
-glamor_push_pixels_nf(GCPtr pGC, PixmapPtr pBitmap,
-                      DrawablePtr pDrawable, int w, int h, int x, int y)
+glamor_push_pixels_nf(GCPtr gc, PixmapPtr bitmap,
+                      DrawablePtr drawable, int w, int h, int x, int y)
 {
-    return _glamor_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y, FALSE);
+    if (glamor_push_pixels_gl(gc, bitmap, drawable, w, h, x, y))
+        return TRUE;
+
+    if (glamor_ddx_fallback_check_pixmap(drawable) &&
+        glamor_ddx_fallback_check_pixmap(&bitmap->drawable) &&
+        glamor_ddx_fallback_check_gc(gc))
+    {
+        return FALSE;
+    }
+
+    miPushPixels(gc, bitmap, drawable, w, h, x, y);
+    return TRUE;
 }
commit 45ebc4e3fac7f1a85167d05e2833949b89f02d64
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 15 13:31:18 2014 -0700

    glamor: Add glamor_program based copy acceleration
    
    Paints with textures, using a temporary buffer for overlapping copies
    
    Performs CPU to GPU transfers for pixmaps in memory. Accelerates copy
    plane when both objects are in the GPU. Includes copy_window
    acceleration too.
    
    v2: Use NV_texture_barrier for non-overlapping copies within the same
    drawable
    
    v3: Switch to glamor_make_current
    
    v4: Do overlap check on the bounding box of the region rather than
        on individual boxes
    
    v5: Use Eric Anholt's re-written comments which provide a more accurate
        description of the code
    
    v6: Use floating point uniform for copy plane bit multiplier. This
        avoids an int to float conversion in the copy plane fragment shader.
    
        Use round() instead of adding 0.5 in copy plane. round() and +0.5
        end up generating equivalent code, and performance measurements
        confirm that they are the same speed. Round() is a bit clearer
        though, so we'll use it.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Markus Wick <markus at selfnet.de>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index cb81872..c0d82d6 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -7,8 +7,7 @@ AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS)
 libglamor_la_SOURCES = \
 	glamor.c \
 	glamor_context.h \
-	glamor_copyarea.c \
-	glamor_copywindow.c \
+	glamor_copy.c \
 	glamor_core.c \
 	glamor_debug.h \
 	glamor_fill.c \
@@ -36,7 +35,6 @@ libglamor_la_SOURCES = \
 	glamor_tile.c \
 	glamor_triangles.c\
 	glamor_addtraps.c\
-	glamor_copyplane.c\
 	glamor_glyphblt.c\
 	glamor_points.c\
 	glamor_priv.h\
diff --git a/glamor/glamor.c b/glamor/glamor.c
index ac23d52..3468b51 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -408,6 +408,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         epoxy_has_gl_extension("GL_ARB_map_buffer_range");
     glamor_priv->has_buffer_storage =
         epoxy_has_gl_extension("GL_ARB_buffer_storage");
+    glamor_priv->has_nv_texture_barrier =
+        epoxy_has_gl_extension("GL_NV_texture_barrier");
     glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
 #ifdef MAX_FBO_SIZE
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
diff --git a/glamor/glamor.h b/glamor/glamor.h
index b0f2212..77fa01e 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -354,6 +354,17 @@ extern _X_EXPORT Bool glamor_copy_n_to_n_nf(DrawablePtr src,
                                             Bool upsidedown, Pixel bitplane,
                                             void *closure);
 
+extern _X_EXPORT Bool glamor_copy_nf(DrawablePtr src,
+                                     DrawablePtr dst,
+                                     GCPtr gc,
+                                     BoxPtr box,
+                                     int nbox,
+                                     int dx,
+                                     int dy,
+                                     Bool reverse,
+                                     Bool upsidedown, Pixel bitplane,
+                                     void *closure);
+
 extern _X_EXPORT Bool glamor_composite_nf(CARD8 op,
                                           PicturePtr source,
                                           PicturePtr mask,
diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c
new file mode 100644
index 0000000..bfcde43
--- /dev/null
+++ b/glamor/glamor_copy.c
@@ -0,0 +1,693 @@
+/*
+ * 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_prepare.h"
+#include "glamor_transform.h"
+
+struct copy_args {
+    PixmapPtr           src_pixmap;
+    glamor_pixmap_fbo   *src;
+    uint32_t            bitplane;
+    int                 dx, dy;
+};
+
+static Bool
+use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
+{
+    struct copy_args *args = arg;
+    glamor_pixmap_fbo *src = args->src;
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, src->tex);
+
+    glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
+    glUniform2f(prog->fill_size_uniform, src->width, src->height);
+
+    return TRUE;
+}
+
+static const glamor_facet glamor_facet_copyarea = {
+    "copy_area",
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = (GLAMOR_POS(gl_Position, primitive.xy)
+                "       fill_pos = (fill_offset + primitive.xy) / fill_size;\n"),
+    .fs_exec = "       gl_FragColor = texture2D(sampler, fill_pos);\n",
+    .locations = glamor_program_location_fill,
+    .use = use_copyarea,
+};
+
+/*
+ * Configure the copy plane program for the current operation
+ */
+
+static Bool
+use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
+{
+    struct copy_args *args = arg;
+    glamor_pixmap_fbo *src = args->src;
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, src->tex);
+
+    glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
+    glUniform2f(prog->fill_size_uniform, src->width, src->height);
+
+    glamor_set_color(dst, gc->fgPixel, prog->fg_uniform);
+    glamor_set_color(dst, gc->bgPixel, prog->bg_uniform);
+
+    /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */
+    switch (args->src_pixmap->drawable.depth) {
+    case 24:
+        glUniform4ui(prog->bitplane_uniform,
+                     (args->bitplane >> 16) & 0xff,
+                     (args->bitplane >>  8) & 0xff,
+                     (args->bitplane      ) & 0xff,
+                     0);
+
+        glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0);
+        break;
+    case 32:
+        glUniform4ui(prog->bitplane_uniform,
+                     (args->bitplane >> 16) & 0xff,
+                     (args->bitplane >>  8) & 0xff,
+                     (args->bitplane      ) & 0xff,
+                     (args->bitplane >> 24) & 0xff);
+
+        glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0xff);
+        break;
+    case 16:
+        glUniform4ui(prog->bitplane_uniform,
+                     (args->bitplane >> 11) & 0x1f,
+                     (args->bitplane >>  5) & 0x3f,
+                     (args->bitplane      ) & 0x1f,
+                     0);
+
+        glUniform4f(prog->bitmul_uniform, 0x1f, 0x3f, 0x1f, 0);
+        break;
+    case 15:
+        glUniform4ui(prog->bitplane_uniform,
+                     (args->bitplane >> 10) & 0x1f,
+                     (args->bitplane >>  5) & 0x1f,
+                     (args->bitplane      ) & 0x1f,
+                     0);
+
+        glUniform4f(prog->bitmul_uniform, 0x1f, 0x1f, 0x1f, 0);
+        break;
+    case 8:
+        glUniform4ui(prog->bitplane_uniform,
+                     0, 0, 0, args->bitplane);
+        glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
+        break;
+    case 1:
+        glUniform4ui(prog->bitplane_uniform,
+                     0, 0, 0, args->bitplane);
+        glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
+        break;
+    }
+
+    return TRUE;
+}
+
+static const glamor_facet glamor_facet_copyplane = {
+    "copy_plane",
+    .version = 130,
+    .vs_vars = "attribute vec2 primitive;\n",
+    .vs_exec = (GLAMOR_POS(gl_Position, (primitive.xy))
+                "       fill_pos = (fill_offset + primitive.xy) / fill_size;\n"),
+    .fs_exec = ("       uvec4 bits = uvec4(round(texture2D(sampler, fill_pos) * bitmul));\n"
+                "       if ((bits & bitplane) != uvec4(0,0,0,0))\n"
+                "               gl_FragColor = fg;\n"
+                "       else\n"
+                "               gl_FragColor = bg;\n"),
+    .locations = glamor_program_location_fill|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane,
+    .use = use_copyplane,
+};
+
+/*
+ * When all else fails, pull the bits out of the GPU and do the
+ * operation with fb
+ */
+
+static void
+glamor_copy_bail(DrawablePtr src,
+                 DrawablePtr dst,
+                 GCPtr gc,
+                 BoxPtr box,
+                 int nbox,
+                 int dx,
+                 int dy,
+                 Bool reverse,
+                 Bool upsidedown,
+                 Pixel bitplane,
+                 void *closure)
+{
+    if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
+        if (bitplane) {
+            if (src->bitsPerPixel > 1)
+                fbCopyNto1(src, dst, gc, box, nbox, dx, dy,
+                           reverse, upsidedown, bitplane, closure);
+            else
+                fbCopy1toN(src, dst, gc, box, nbox, dx, dy,
+                           reverse, upsidedown, bitplane, closure);
+        } else {
+            fbCopyNtoN(src, dst, gc, box, nbox, dx, dy,
+                       reverse, upsidedown, bitplane, closure);
+        }
+    }
+    glamor_finish_access(dst);
+    glamor_finish_access(src);
+}
+
+/**
+ * Implements CopyPlane and CopyArea from the GPU to the GPU by using
+ * the source as a texture and painting that into the destination.
+ *
+ * This requires that source and dest are different textures, or that
+ * (if the copy area doesn't overlap), GL_NV_texture_barrier is used
+ * to ensure that the caches are flushed at the right times.
+ */
+static Bool
+glamor_copy_cpu_fbo(DrawablePtr src,
+                    DrawablePtr dst,
+                    GCPtr gc,
+                    BoxPtr box,
+                    int nbox,
+                    int dx,
+                    int dy,
+                    Bool reverse,
+                    Bool upsidedown,
+                    Pixel bitplane,
+                    void *closure)
+{
+    ScreenPtr screen = dst->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
+    FbBits *src_bits;
+    FbStride src_stride;
+    int src_bpp;
+    int src_xoff, src_yoff;
+    int dst_xoff, dst_yoff;
+
+    if (gc && gc->alu != GXcopy)
+        goto bail;
+
+    if (gc && !glamor_pm_is_solid(dst, gc->planemask))
+        goto bail;
+
+    glamor_make_current(glamor_priv);
+    glamor_prepare_access(src, GLAMOR_ACCESS_RO);
+
+    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);
+
+    fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff);
+
+    glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy,
+                        dst_xoff, dst_yoff,
+                        (uint8_t *) src_bits, src_stride * sizeof (FbBits));
+    glamor_finish_access(src);
+
+    return TRUE;
+
+bail:
+    return FALSE;
+}
+
+/*
+ * Copy from GPU to GPU by using the source
+ * as a texture and painting that into the destination
+ */
+
+static Bool
+glamor_copy_fbo_fbo_draw(DrawablePtr src,
+                         DrawablePtr dst,
+                         GCPtr gc,
+                         BoxPtr box,
+                         int nbox,
+                         int dx,
+                         int dy,
+                         Bool reverse,
+                         Bool upsidedown,
+                         Pixel bitplane,
+                         void *closure)
+{
+    ScreenPtr screen = dst->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
+    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
+    glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
+    glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
+    int src_box_x, src_box_y, dst_box_x, dst_box_y;
+    int dst_off_x, dst_off_y;
+    int src_off_x, src_off_y;
+    GLshort *v;
+    char *vbo_offset;
+    struct copy_args args;
+    glamor_program *prog;
+    const glamor_facet *copy_facet;
+    Bool set_scissor;
+    int n;
+
+    glamor_make_current(glamor_priv);
+
+    if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask))
+        goto bail_ctx;
+
+    if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
+        goto bail_ctx;
+
+    if (bitplane) {
+        prog = &glamor_priv->copy_plane_prog;
+        copy_facet = &glamor_facet_copyplane;
+    } else {
+        prog = &glamor_priv->copy_area_prog;
+        copy_facet = &glamor_facet_copyarea;
+    }
+
+    if (prog->failed)
+        goto bail_ctx;
+
+    if (!prog->prog) {
+        if (!glamor_build_program(screen, prog,
+                                  copy_facet, NULL))
+            goto bail_ctx;
+    }
+
+    args.src_pixmap = src_pixmap;
+    args.bitplane = bitplane;
+
+    /* Set up the vertex buffers for the points */
+
+    v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset);
+
+    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
+                          2 * sizeof (GLshort), vbo_offset);
+
+    for (n = 0; n < nbox; n++) {
+        v[0] = box->x1; v[1] = box->y1;
+        v[2] = box->x1; v[3] = box->y2;
+        v[4] = box->x2; v[5] = box->y2;
+        v[6] = box->x2; v[7] = box->y1;
+        v += 8;
+        box++;
+    }
+
+    glamor_put_vbo_space(screen);
+
+    glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
+
+    set_scissor = src_priv->type == GLAMOR_TEXTURE_LARGE;
+    if (set_scissor)
+        glEnable(GL_SCISSOR_TEST);
+
+    glamor_pixmap_loop(src_priv, src_box_x, src_box_y) {
+        BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_x, src_box_y);
+
+        args.dx = dx + src_off_x - src_box->x1;
+        args.dy = dy + src_off_y - src_box->y1;
+        args.src = glamor_pixmap_fbo_at(src_priv, src_box_x, src_box_y);
+
+        if (!glamor_use_program(dst_pixmap, gc, prog, &args))
+            goto bail_ctx;
+
+        glamor_pixmap_loop(dst_priv, dst_box_x, dst_box_y) {
+            glamor_set_destination_drawable(dst, dst_box_x, dst_box_y, FALSE, FALSE,
+                                            prog->matrix_uniform, &dst_off_x, &dst_off_y);
+
+            if (set_scissor)
+                glScissor(dst_off_x - args.dx,
+                          dst_off_y - args.dy,
+                          src_box->x2 - src_box->x1,
+                          src_box->y2 - src_box->y1);
+
+            if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
+                glDrawArrays(GL_QUADS, 0, nbox * 4);
+            else {
+                int i;
+                for (i = 0; i < nbox; i++)
+                    glDrawArrays(GL_TRIANGLE_FAN, i*4, 4);
+            }
+        }
+    }
+    if (set_scissor)
+        glDisable(GL_SCISSOR_TEST);
+    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+
+    glDisable(GL_COLOR_LOGIC_OP);
+    return TRUE;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    return FALSE;
+}
+
+/**
+ * Copies from the GPU to the GPU using a temporary pixmap in between,
+ * to correctly handle overlapping copies.
+ */
+
+static Bool
+glamor_copy_fbo_fbo_temp(DrawablePtr src,
+                         DrawablePtr dst,
+                         GCPtr gc,
+                         BoxPtr box,
+                         int nbox,
+                         int dx,
+                         int dy,
+                         Bool reverse,
+                         Bool upsidedown,
+                         Pixel bitplane,
+                         void *closure)
+{
+    ScreenPtr screen = dst->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
+    PixmapPtr tmp_pixmap;
+    BoxRec bounds;
+    int n;
+    BoxPtr tmp_box;
+
+    if (nbox == 0)
+        return TRUE;
+
+    /* Sanity check state to avoid getting halfway through and bailing
+     * at the last second. Might be nice to have checks that didn't
+     * involve setting state.
+     */
+    glamor_make_current(glamor_priv);
+
+    if (gc && !glamor_set_planemask(dst_pixmap, gc->planemask))
+        goto bail_ctx;
+
+    if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
+        goto bail_ctx;
+    glDisable(GL_COLOR_LOGIC_OP);
+
+    /* Find the size of the area to copy
+     */
+    bounds = box[0];
+    for (n = 1; n < nbox; n++) {
+        bounds.x1 = min(bounds.x1, box[n].x1);
+        bounds.x2 = max(bounds.x2, box[n].x2);
+        bounds.y1 = min(bounds.y1, box[n].y1);
+        bounds.y2 = max(bounds.y2, box[n].y2);
+    }
+
+    /* Allocate a suitable temporary pixmap
+     */
+    tmp_pixmap = glamor_create_pixmap(screen,
+                                      bounds.x2 - bounds.x1,
+                                      bounds.y2 - bounds.y1,
+                                      src->depth, 0);
+    if (!tmp_pixmap)
+        goto bail;
+
+    tmp_box = calloc(nbox, sizeof (BoxRec));
+    if (!tmp_box)
+        goto bail_pixmap;
+
+    /* Convert destination boxes into tmp pixmap boxes
+     */
+    for (n = 0; n < nbox; n++) {
+        tmp_box[n].x1 = box[n].x1 - bounds.x1;
+        tmp_box[n].x2 = box[n].x2 - bounds.x1;
+        tmp_box[n].y1 = box[n].y1 - bounds.y1;
+        tmp_box[n].y2 = box[n].y2 - bounds.y1;
+    }
+
+    if (!glamor_copy_fbo_fbo_draw(src,
+                                  &tmp_pixmap->drawable,
+                                  NULL,
+                                  tmp_box,
+                                  nbox,
+                                  dx + bounds.x1,
+                                  dy + bounds.y1,
+                                  FALSE, FALSE,
+                                  0, NULL))
+        goto bail_box;
+
+    if (!glamor_copy_fbo_fbo_draw(&tmp_pixmap->drawable,
+                                  dst,
+                                  gc,
+                                  box,
+                                  nbox,
+                                  -bounds.x1,
+                                  -bounds.y1,
+                                  FALSE, FALSE,
+                                  bitplane, closure))
+        goto bail_box;
+
+    free(tmp_box);
+
+    glamor_destroy_pixmap(tmp_pixmap);
+
+    return TRUE;
+bail_box:
+    free(tmp_box);
+bail_pixmap:
+    glamor_destroy_pixmap(tmp_pixmap);
+bail:
+    return FALSE;
+
+bail_ctx:
+    glDisable(GL_COLOR_LOGIC_OP);
+    return FALSE;
+}
+
+/**
+ * Returns TRUE if the copy has to be implemented with
+ * glamor_copy_fbo_fbo_temp() instead of glamor_copy_fbo_fbo().
+ *
+ * If the src and dst are in the same pixmap, then glamor_copy_fbo_fbo()'s
+ * sampling would give undefined results (since the same texture would be
+ * bound as an FBO destination and as a texture source).  However, if we
+ * have GL_NV_texture_barrier, we can take advantage of the exception it
+ * added:
+ *
+ *    "- If a texel has been written, then in order to safely read the result
+ *       a texel fetch must be in a subsequent Draw separated by the command
+ *
+ *       void TextureBarrierNV(void);
+ *
+ *    TextureBarrierNV() will guarantee that writes have completed and caches
+ *    have been invalidated before subsequent Draws are executed."
+ */
+static Bool
+glamor_copy_needs_temp(DrawablePtr src,
+                       DrawablePtr dst,
+                       BoxPtr box,
+                       int nbox,
+                       int dx,
+                       int dy)
+{
+    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
+    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
+    ScreenPtr screen = dst->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    int n;
+    int dst_off_x, dst_off_y;
+    int src_off_x, src_off_y;
+    BoxRec bounds;
+
+    if (src_pixmap != dst_pixmap)
+        return FALSE;
+
+    if (nbox == 0)
+        return FALSE;
+
+    if (!glamor_priv->has_nv_texture_barrier)
+        return TRUE;
+
+    glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
+    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y);
+
+    bounds = box[0];
+    for (n = 1; n < nbox; n++) {
+        bounds.x1 = min(bounds.x1, box[n].x1);
+        bounds.y1 = min(bounds.y1, box[n].y1);
+
+        bounds.x2 = max(bounds.x2, box[n].x2);
+        bounds.y2 = max(bounds.y2, box[n].y2);
+    }
+
+    /* Check to see if the pixmap-relative boxes overlap in both X and Y,
+     * in which case we can't rely on NV_texture_barrier and must
+     * make a temporary copy
+     *
+     *  dst.x1                     < src.x2 &&
+     *  src.x1                     < dst.x2 &&
+     *
+     *  dst.y1                     < src.y2 &&
+     *  src.y1                     < dst.y2
+     */
+    if (bounds.x1 + dst_off_x      < bounds.x2 + dx + src_off_x &&
+        bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x &&
+
+        bounds.y1 + dst_off_y      < bounds.y2 + dy + src_off_y &&
+        bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) {
+        return TRUE;
+    }
+
+    glTextureBarrierNV();
+
+    return FALSE;
+}
+
+static Bool
+glamor_copy_gl(DrawablePtr src,
+               DrawablePtr dst,
+               GCPtr gc,
+               BoxPtr box,
+               int nbox,
+               int dx,
+               int dy,
+               Bool reverse,
+               Bool upsidedown,
+               Pixel bitplane,
+               void *closure)
+{
+    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
+    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
+    glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
+    glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
+
+    if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv)) {
+        if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv)) {
+            if (glamor_copy_needs_temp(src, dst, box, nbox, dx, dy))
+                return glamor_copy_fbo_fbo_temp(src, dst, gc, box, nbox, dx, dy,
+                                                reverse, upsidedown, bitplane, closure);
+            else
+                return glamor_copy_fbo_fbo_draw(src, dst, gc, box, nbox, dx, dy,
+                                                reverse, upsidedown, bitplane, closure);
+        }
+        if (bitplane == 0)
+            return glamor_copy_cpu_fbo(src, dst, gc, box, nbox, dx, dy,
+                                       reverse, upsidedown, bitplane, closure);
+    }
+    return FALSE;
+}
+
+void
+glamor_copy(DrawablePtr src,
+            DrawablePtr dst,
+            GCPtr gc,
+            BoxPtr box,
+            int nbox,
+            int dx,
+            int dy,
+            Bool reverse,
+            Bool upsidedown,
+            Pixel bitplane,
+            void *closure)
+{
+    if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
+        return;
+    glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
+}
+
+RegionPtr
+glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+                 int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+    return miDoCopy(src, dst, gc,
+                    srcx, srcy, width, height,
+                    dstx, dsty, glamor_copy, 0, NULL);
+}
+
+RegionPtr
+glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+                  int srcx, int srcy, int width, int height, int dstx, int dsty,
+                  unsigned long bitplane)
+{
+    if ((bitplane & FbFullMask(src->depth)) == 0)
+        return miHandleExposures(src, dst, gc,
+                                 srcx, srcy, width, height, dstx, dsty,
+                                 bitplane);
+    return miDoCopy(src, dst, gc,
+                    srcx, srcy, width, height,
+                    dstx, dsty, glamor_copy, bitplane, NULL);
+}
+
+void
+glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(&window->drawable);
+    DrawablePtr drawable = &pixmap->drawable;
+    RegionRec dst_region;
+    int dx, dy;
+
+    dx = old_origin.x - window->drawable.x;
+    dy = old_origin.y - window->drawable.y;
+    RegionTranslate(src_region, -dx, -dy);
+
+    RegionNull(&dst_region);
+
+    RegionIntersect(&dst_region, &window->borderClip, src_region);
+
+#ifdef COMPOSITE
+    if (pixmap->screen_x || pixmap->screen_y)
+        RegionTranslate(&dst_region, -pixmap->screen_x, -pixmap->screen_y);
+#endif
+
+    miCopyRegion(drawable, drawable,
+                 0, &dst_region, dx, dy, glamor_copy, 0, 0);
+
+    RegionUninit(&dst_region);
+}
+
+Bool
+glamor_copy_n_to_n_nf(DrawablePtr src,
+                      DrawablePtr dst,
+                      GCPtr gc,
+                      BoxPtr box,
+                      int nbox,
+                      int dx,
+                      int dy,
+                      Bool reverse,
+                      Bool upsidedown, Pixel bitplane,
+                      void *closure)
+{
+    if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
+        return TRUE;
+    if (glamor_ddx_fallback_check_pixmap(src) && glamor_ddx_fallback_check_pixmap(dst))
+        return FALSE;
+    glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
+    return TRUE;
+}
+
+Bool
+glamor_copy_plane_nf(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+                     int srcx, int srcy, int w, int h, int dstx, int dsty,
+                     unsigned long bitplane, RegionPtr *region)
+{
+    if (glamor_ddx_fallback_check_pixmap(src) &&
+        glamor_ddx_fallback_check_pixmap(dst) &&
+        glamor_ddx_fallback_check_gc(gc))
+        return FALSE;
+
+    *region = glamor_copy_plane(src, dst, gc,
+                                srcx, srcy, w, h, dstx, dsty,
+                                bitplane);
+    return TRUE;
+}
diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c
deleted file mode 100644
index e198822..0000000
--- a/glamor/glamor_copyarea.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright © 2008 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Keith Packard makes no
- * representations about the suitability of this software for any purpose.  It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric at anholt.net>
- *    Zhigang Gong <zhigang.gong at linux.intel.com>
- */
-
-#include "glamor_priv.h"
-
-/** @file glamor_copyarea.c
- *
- * GC CopyArea implementation
- */
-static Bool
-glamor_copy_n_to_n_fbo_blit(DrawablePtr src,
-                            DrawablePtr dst,
-                            GCPtr gc, BoxPtr box, int nbox, int dx, int dy)
-{
-    ScreenPtr screen = dst->pScreen;
-    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
-    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
-    glamor_pixmap_private *src_pixmap_priv, *dst_pixmap_priv;
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    int dst_x_off, dst_y_off, src_x_off, src_y_off, i;
-    int fbo_x_off, fbo_y_off;
-    int src_fbo_x_off, src_fbo_y_off;
-
-    if (!glamor_priv->has_fbo_blit) {
-        glamor_delayed_fallback(screen, "no EXT_framebuffer_blit\n");
-        return FALSE;
-    }
-    src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
-    dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
-
-    if (gc) {
-        if (gc->alu != GXcopy) {
-            glamor_delayed_fallback(screen, "non-copy ALU\n");
-            return FALSE;
-        }
-    }
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)) {
-        glamor_delayed_fallback(screen, "no src fbo\n");
-        return FALSE;
-    }
-
-    if (glamor_set_destination_pixmap(dst_pixmap))
-        return FALSE;
-
-    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_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);
-    dst_x_off += fbo_x_off;
-    dst_y_off += fbo_y_off;
-    src_y_off += dy + src_fbo_y_off;
-    src_x_off += src_fbo_x_off;
-
-    for (i = 0; i < nbox; i++) {
-        if (glamor_priv->yInverted) {
-            glBlitFramebuffer(box[i].x1 + dx + src_x_off,
-                              box[i].y1 + src_y_off,
-                              box[i].x2 + dx + src_x_off,
-                              box[i].y2 + src_y_off,
-                              box[i].x1 + dst_x_off,
-                              box[i].y1 + dst_y_off,
-                              box[i].x2 + dst_x_off,
-                              box[i].y2 + dst_y_off,
-                              GL_COLOR_BUFFER_BIT, GL_NEAREST);
-        }
-        else {
-            int flip_dst_y1 =
-                dst_pixmap->drawable.height - (box[i].y2 + dst_y_off);
-            int flip_dst_y2 =
-                dst_pixmap->drawable.height - (box[i].y1 + dst_y_off);
-            int flip_src_y1 =
-                src_pixmap->drawable.height - (box[i].y2 + src_y_off);
-            int flip_src_y2 =
-                src_pixmap->drawable.height - (box[i].y1 + src_y_off);
-
-            glBlitFramebuffer(box[i].x1 + dx + src_x_off,
-                              flip_src_y1,
-                              box[i].x2 + dx + src_x_off,
-                              flip_src_y2,
-                              box[i].x1 + dst_x_off,
-                              flip_dst_y1,
-                              box[i].x2 + dst_x_off,
-                              flip_dst_y2,
-                              GL_COLOR_BUFFER_BIT, GL_NEAREST);
-        }
-    }
-    glamor_priv->state = BLIT_STATE;
-    return TRUE;
-}
-
-static Bool
-glamor_copy_n_to_n_textured(DrawablePtr src,
-                            DrawablePtr dst,
-                            GCPtr gc, BoxPtr box, int nbox, int dx, int dy)
-{
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(dst->pScreen);
-    PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
-    PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
-    int i;
-    float vertices[8], texcoords[8];
-    glamor_pixmap_private *src_pixmap_priv;
-    glamor_pixmap_private *dst_pixmap_priv;
-    int src_x_off, src_y_off, dst_x_off, dst_y_off;
-    enum glamor_pixmap_status src_status = GLAMOR_NONE;
-    GLfloat dst_xscale, dst_yscale, src_xscale, src_yscale;
-
-    src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
-    dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
-
-    if (src_pixmap_priv->base.gl_fbo == GLAMOR_FBO_UNATTACHED) {
-#ifndef GLAMOR_PIXMAP_DYNAMIC_UPLOAD
-        glamor_delayed_fallback(dst->pScreen, "src has no fbo.\n");
-        return FALSE;
-#else
-        src_status = glamor_upload_pixmap_to_texture(src_pixmap);
-        if (src_status != GLAMOR_UPLOAD_DONE)
-            return FALSE;
-
-        src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
-#endif
-    }
-
-    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_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
-
-    glamor_make_current(glamor_priv);
-
-    glamor_set_destination_pixmap_priv_nc(dst_pixmap_priv);
-    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                          GL_FALSE, 2 * sizeof(float), vertices);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-
-    glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
-    dx += src_x_off;
-    dy += src_y_off;
-
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, src_pixmap_priv->base.fbo->tex);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
-    }
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, GL_FALSE,
-                          2 * sizeof(float), texcoords);
-    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    glUseProgram(glamor_priv->finish_access_prog[0]);
-    glUniform1i(glamor_priv->finish_access_revert[0], REVERT_NONE);
-    glUniform1i(glamor_priv->finish_access_swap_rb[0], SWAP_NONE_UPLOADING);
-
-    for (i = 0; i < nbox; i++) {
-
-        glamor_set_normalize_vcoords(dst_pixmap_priv,
-                                     dst_xscale, dst_yscale,
-                                     box[i].x1 + dst_x_off,
-                                     box[i].y1 + dst_y_off,
-                                     box[i].x2 + dst_x_off,
-                                     box[i].y2 + dst_y_off,
-                                     glamor_priv->yInverted, vertices);
-
-        glamor_set_normalize_tcoords(src_pixmap_priv,
-                                     src_xscale,
-                                     src_yscale,
-                                     box[i].x1 + dx,
-                                     box[i].y1 + dy,
-                                     box[i].x2 + dx,
-                                     box[i].y2 + dy,
-                                     glamor_priv->yInverted, texcoords);
-        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-    }
-
-    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-    /* The source texture is bound to a fbo, we have to flush it here. */
-    glamor_priv->state = RENDER_STATE;
-    glamor_priv->render_idle_cnt = 0;
-    return TRUE;
-}
-
-static Bool
-__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)
-{
-    PixmapPtr dst_pixmap, src_pixmap, temp_pixmap = NULL;
-    DrawablePtr temp_src = src;
-    glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
-    glamor_screen_private *glamor_priv;
-    BoxRec bound;
-    ScreenPtr screen;
-    int temp_dx = dx;
-    int temp_dy = dy;
-    int src_x_off, src_y_off, dst_x_off, dst_y_off;
-    int i;
-    int overlaped = 0;
-    Bool ret = FALSE;
-
-    dst_pixmap = glamor_get_drawable_pixmap(dst);
-    dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
-    src_pixmap = glamor_get_drawable_pixmap(src);
-    src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
-    screen = dst_pixmap->drawable.pScreen;
-    glamor_priv = glamor_get_screen_private(dst->pScreen);
-    glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
-
-    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
-
-    if (src_pixmap_priv->base.fbo
-        && src_pixmap_priv->base.fbo->fb == dst_pixmap_priv->base.fbo->fb) {
-        int x_shift = abs(src_x_off - dx - dst_x_off);
-        int y_shift = abs(src_y_off - dy - dst_y_off);
-
-        for (i = 0; i < nbox; i++) {
-            if (x_shift < abs(box[i].x2 - box[i].x1)
-                && y_shift < abs(box[i].y2 - box[i].y1)) {
-                overlaped = 1;
-                break;
-            }
-        }
-    }
-    DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
-           box[0].x1, box[0].y1,
-           box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
-           dx, dy, src_pixmap, dst_pixmap);
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP &&
-        !overlaped &&
-        (glamor_priv->state != RENDER_STATE
-         || !src_pixmap_priv->base.gl_tex || !dst_pixmap_priv->base.gl_tex)
-        && glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) {
-        ret = TRUE;
-        goto done;
-    }
-    glamor_calculate_boxes_bound(&bound, box, nbox);
-
-    /*  Overlaped indicate the src and dst are the same pixmap. */
-    if (overlaped || (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv)
-                      && (((bound.x2 - bound.x1) * (bound.y2 - bound.y1)
-                           * 4 >
-                           src_pixmap->drawable.width *
-                           src_pixmap->drawable.height)
-                          || !(glamor_check_fbo_size(glamor_priv,
-                                                     src_pixmap->drawable.width,
-                                                     src_pixmap->drawable.
-                                                     height))))) {
-
-        temp_pixmap = glamor_create_pixmap(screen,
-                                           bound.x2 - bound.x1,
-                                           bound.y2 - bound.y1,
-                                           src_pixmap->drawable.depth,
-                                           overlaped ? 0 :
-                                           GLAMOR_CREATE_PIXMAP_CPU);
-        assert(bound.x2 - bound.x1 <= glamor_priv->max_fbo_size);
-        assert(bound.y2 - bound.y1 <= glamor_priv->max_fbo_size);
-        if (!temp_pixmap)
-            goto done;
-        glamor_translate_boxes(box, nbox, -bound.x1, -bound.y1);
-        temp_src = &temp_pixmap->drawable;
-
-        if (overlaped)
-            glamor_copy_n_to_n_textured(src, temp_src, gc, box,
-                                        nbox,
-                                        temp_dx + bound.x1, temp_dy + bound.y1);
-        else
-            fbCopyNtoN(src, temp_src, gc, box, nbox,
-                       temp_dx + bound.x1, temp_dy + bound.y1,
-                       reverse, upsidedown, bitplane, closure);
-        glamor_translate_boxes(box, nbox, bound.x1, bound.y1);
-        temp_dx = -bound.x1;
-        temp_dy = -bound.y1;
-    }
-    else {
-        temp_dx = dx;
-        temp_dy = dy;
-        temp_src = src;
-    }
-
-    if (glamor_copy_n_to_n_textured
-        (temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) {
-        ret = TRUE;
-    }
- done:
-    if (temp_src != src)
-        glamor_destroy_pixmap(temp_pixmap);
-    return ret;
-}
-
-static Bool
-_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, Bool fallback)
-{
-    ScreenPtr screen = dst->pScreen;
-    PixmapPtr dst_pixmap, src_pixmap;
-    glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
-    glamor_screen_private *glamor_priv;
-    BoxPtr extent;
-    RegionRec region;
-    int src_x_off, src_y_off, dst_x_off, dst_y_off;
-    Bool ok = FALSE;
-    int force_clip = 0;
-
-    if (nbox == 0)
-        return TRUE;
-    dst_pixmap = glamor_get_drawable_pixmap(dst);
-    dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
-    src_pixmap = glamor_get_drawable_pixmap(src);
-    src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
-
-    glamor_priv = glamor_get_screen_private(screen);
-
-    DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
-           box[0].x1, box[0].y1,
-           box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
-           dx, dy, src_pixmap, dst_pixmap);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
-        goto fall_back;
-
-    if (gc) {
-        if (!glamor_set_planemask(dst_pixmap, gc->planemask))
-            goto fall_back;
-        glamor_make_current(glamor_priv);
-        if (!glamor_set_alu(screen, gc->alu)) {
-            goto fail_noregion;
-        }
-    }
-
-    if (!src_pixmap_priv) {
-        glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY);
-        src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
-    }
-
-    glamor_get_drawable_deltas(src, src_pixmap, &src_x_off, &src_y_off);
-    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off, &dst_y_off);
-
-    RegionInitBoxes(&region, box, nbox);
-    extent = RegionExtents(&region);
-
-    if (!glamor_check_fbo_size(glamor_priv,
-                               extent->x2 - extent->x1, extent->y2 - extent->y1)
-        && (src_pixmap_priv->type == GLAMOR_MEMORY
-            || (src_pixmap_priv == dst_pixmap_priv))) {
-        force_clip = 1;
-    }
-
-    if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
-        || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
-        glamor_pixmap_clipped_regions *clipped_dst_regions;
-        int n_dst_region, i, j;
-        PixmapPtr temp_source_pixmap;
-        glamor_pixmap_private *temp_source_priv = NULL;
-
-        RegionTranslate(&region, dst_x_off, dst_y_off);
-        if (!force_clip)
-            clipped_dst_regions =
-                glamor_compute_clipped_regions(dst_pixmap_priv, &region,
-                                               &n_dst_region, 0, reverse,
-                                               upsidedown);
-        else
-            clipped_dst_regions =
-                glamor_compute_clipped_regions_ext(dst_pixmap_priv, &region,
-                                                   &n_dst_region,
-                                                   glamor_priv->max_fbo_size,
-                                                   glamor_priv->max_fbo_size,
-                                                   reverse, upsidedown);
-        for (i = 0; i < n_dst_region; i++) {
-            int n_src_region;
-            glamor_pixmap_clipped_regions *clipped_src_regions;
-            BoxPtr current_boxes;
-            int n_current_boxes;
-
-            SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv,
-                                   clipped_dst_regions[i].block_idx);
-
-            temp_source_pixmap = NULL;
-            if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
-                RegionTranslate(clipped_dst_regions[i].region,
-                                -dst_x_off + src_x_off + dx,
-                                -dst_y_off + src_y_off + dy);
-                clipped_src_regions =
-                    glamor_compute_clipped_regions(src_pixmap_priv,
-                                                   clipped_dst_regions[i].
-                                                   region, &n_src_region, 0,
-                                                   reverse, upsidedown);
-                DEBUGF("Source is large pixmap.\n");
-                for (j = 0; j < n_src_region; j++) {
-                    if (src_pixmap_priv != dst_pixmap_priv)
-                        SET_PIXMAP_FBO_CURRENT(src_pixmap_priv,
-                                               clipped_src_regions[j].
-                                               block_idx);
-                    else if (src_pixmap_priv == dst_pixmap_priv &&
-                             clipped_src_regions[j].block_idx !=
-                             clipped_dst_regions[i].block_idx) {
-                        /* source and the dest are the same, but need different block_idx.
-                         * we create a empty pixmap and fill the required source fbo and box to
-                         * it. It's a little hacky, but avoid extra copy. */
-                        temp_source_pixmap =
-                            glamor_create_pixmap(src->pScreen, 0, 0, src->depth,
-                                                 0);
-                        if (!temp_source_pixmap) {
-                            ok = FALSE;
-                            goto fail;
-                        }
-                        src->pScreen->ModifyPixmapHeader(temp_source_pixmap,
-                                                         src_pixmap->drawable.
-                                                         width,
-                                                         src_pixmap->drawable.
-                                                         height, 0, 0,
-                                                         src_pixmap->devKind,
-                                                         NULL);
-                        temp_source_priv =
-                            glamor_get_pixmap_private(temp_source_pixmap);
-                        *temp_source_priv = *src_pixmap_priv;
-                        temp_source_priv->large.box =
-                            src_pixmap_priv->large.
-                            box_array[clipped_src_regions[j].block_idx];
-                        temp_source_priv->base.fbo =
-                            src_pixmap_priv->large.
-                            fbo_array[clipped_src_regions[j].block_idx];
-                        temp_source_priv->base.pixmap = temp_source_pixmap;
-                    }
-                    assert(temp_source_pixmap ||
-                           !(src_pixmap_priv == dst_pixmap_priv &&
-                             (clipped_src_regions[j].block_idx !=
-                              clipped_dst_regions[i].block_idx)));
-
-                    RegionTranslate(clipped_src_regions[j].region,
-                                    -src_x_off - dx, -src_y_off - dy);
-                    current_boxes = RegionRects(clipped_src_regions[j].region);
-                    n_current_boxes =
-                        RegionNumRects(clipped_src_regions[j].region);
-                    DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n",
-                           clipped_dst_regions[i].block_idx,
-                           clipped_src_regions[j].block_idx);
-                    DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n",
-                           current_boxes[0].x1, current_boxes[0].y1,
-                           current_boxes[0].x2, current_boxes[0].y2, dx, dy,
-                           src_pixmap, dst_pixmap);
-                    if (!temp_source_pixmap)
-                        ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes,
-                                                  n_current_boxes, dx, dy,
-                                                  reverse, upsidedown, bitplane,
-                                                  closure);
-                    else {
-                        ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable,
-                                                  dst, gc, current_boxes,
-                                                  n_current_boxes, dx, dy,
-                                                  reverse, upsidedown, bitplane,
-                                                  closure);
-                        temp_source_priv->type = GLAMOR_MEMORY;
-                        temp_source_priv->base.fbo = NULL;
-                        glamor_destroy_pixmap(temp_source_pixmap);
-                        temp_source_pixmap = NULL;
-                    }
-
-                    RegionDestroy(clipped_src_regions[j].region);
-                    if (!ok) {
-                        assert(0);
-                        goto fail;
-                    }
-                }
-
-                if (n_src_region == 0)
-                    ok = TRUE;
-                free(clipped_src_regions);
-            }
-            else {
-                RegionTranslate(clipped_dst_regions[i].region,
-                                -dst_x_off, -dst_y_off);
-                current_boxes = RegionRects(clipped_dst_regions[i].region);
-                n_current_boxes = RegionNumRects(clipped_dst_regions[i].region);
-
-                DEBUGF("dest pixmap fbo idx %d \n",
-                       clipped_dst_regions[i].block_idx);
-                DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n",
-                       current_boxes[0].x1, current_boxes[0].y1,
-                       current_boxes[0].x2, current_boxes[0].y2,
-                       dx, dy, src_pixmap, dst_pixmap);
-
-                ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes,
-                                          n_current_boxes, dx, dy, reverse,
-                                          upsidedown, bitplane, closure);
-
-            }
-            RegionDestroy(clipped_dst_regions[i].region);
-        }
-        if (n_dst_region == 0)
-            ok = TRUE;
-        free(clipped_dst_regions);
-    }
-    else {
-        ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy,
-                                  reverse, upsidedown, bitplane, closure);
-    }
-
- fail:
-    RegionUninit(&region);
- fail_noregion:
-    glamor_make_current(glamor_priv);
-    glamor_set_alu(screen, GXcopy);
-
-    if (ok)
-        return TRUE;
- fall_back:
-    if (!fallback && glamor_ddx_fallback_check_pixmap(src)
-        && glamor_ddx_fallback_check_pixmap(dst))
-        goto done;
-
-    if (src_pixmap_priv->type == GLAMOR_DRM_ONLY
-        || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) {
-        LogMessage(X_WARNING,
-                   "Access a DRM only pixmap is not allowed within glamor.\n");
-        return TRUE;
-    }
-    glamor_report_delayed_fallbacks(src->pScreen);
-    glamor_report_delayed_fallbacks(dst->pScreen);
-
-    glamor_fallback("from %p to %p (%c,%c)\n", src, dst,
-                    glamor_get_drawable_location(src),
-                    glamor_get_drawable_location(dst));
-
-    if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access(src, GLAMOR_ACCESS_RO) &&
-        glamor_prepare_access_gc(gc)) {
-        fbCopyNtoN(src, dst, gc, box, nbox,
-                   dx, dy, reverse, upsidedown, bitplane, closure);
-    }
-    glamor_finish_access_gc(gc);
-    glamor_finish_access(src);
-    glamor_finish_access(dst);
-    ok = TRUE;
-
- done:
-    glamor_clear_delayed_fallbacks(src->pScreen);
-    glamor_clear_delayed_fallbacks(dst->pScreen);
-    return ok;
-}
-
-RegionPtr
-glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
-                 int srcx, int srcy, int width, int height, int dstx, int dsty)
-{
-    RegionPtr region;
-
-    region = miDoCopy(src, dst, gc,
-                      srcx, srcy, width, height,
-                      dstx, dsty, glamor_copy_n_to_n, 0, NULL);
-
-    return region;
-}
-
-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_copy_n_to_n(src, dst, gc, box, nbox, dx,
-                        dy, reverse, upsidedown, bitplane, closure, TRUE);
-}
-
-Bool
-glamor_copy_n_to_n_nf(DrawablePtr src,
-                      DrawablePtr dst,
-                      GCPtr gc,
-                      BoxPtr box,
-                      int nbox,
-                      int dx,
-                      int dy,
-                      Bool reverse,
-                      Bool upsidedown, Pixel bitplane, void *closure)
-{
-    return _glamor_copy_n_to_n(src, dst, gc, box, nbox, dx,
-                               dy, reverse, upsidedown, bitplane, closure,
-                               FALSE);
-}
diff --git a/glamor/glamor_copyplane.c b/glamor/glamor_copyplane.c
deleted file mode 100644
index 2bd2de3..0000000
--- a/glamor/glamor_copyplane.c
+++ /dev/null
@@ -1,75 +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_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
-                   int srcx, int srcy, int w, int h, int dstx, int dsty,
-                   unsigned long bitPlane, RegionPtr *pRegion, Bool fallback)
-{
-    if (!fallback && glamor_ddx_fallback_check_gc(pGC)
-        && glamor_ddx_fallback_check_pixmap(pSrc)
-        && glamor_ddx_fallback_check_pixmap(pDst))
-        goto fail;
-
-    if (glamor_prepare_access(pDst, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access(pSrc, GLAMOR_ACCESS_RO) &&
-        glamor_prepare_access_gc(pGC)) {
-        *pRegion = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
-                               dstx, dsty, bitPlane);
-    }
-    glamor_finish_access_gc(pGC);
-    glamor_finish_access(pSrc);
-    glamor_finish_access(pDst);
-    return TRUE;
-
- fail:
-    return FALSE;
-}
-
-RegionPtr
-glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
-                  int srcx, int srcy, int w, int h, int dstx, int dsty,
-                  unsigned long bitPlane)
-{
-    RegionPtr ret;
-
-    _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
-                       dstx, dsty, bitPlane, &ret, TRUE);
-    return ret;
-}
-
-Bool
-glamor_copy_plane_nf(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
-                     int srcx, int srcy, int w, int h, int dstx, int dsty,
-                     unsigned long bitPlane, RegionPtr *pRegion)
-{
-    return _glamor_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
-                              dstx, dsty, bitPlane, pRegion, FALSE);
-}
diff --git a/glamor/glamor_copywindow.c b/glamor/glamor_copywindow.c
deleted file mode 100644
index 1ced4b3..0000000
--- a/glamor/glamor_copywindow.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright © 2008 Intel Corporation
- * Copyright © 1998 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Keith Packard makes no
- * representations about the suitability of this software for any purpose.  It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "glamor_priv.h"
-
-/** @file glamor_copywindow.c
- *
- * Screen CopyWindow implementation.
- */
-
-void
-glamor_copy_window(WindowPtr win, DDXPointRec old_origin, RegionPtr src_region)
-{
-    RegionRec dst_region;
-    int dx, dy;
-    PixmapPtr pixmap = win->drawable.pScreen->GetWindowPixmap(win);
-
-    dx = old_origin.x - win->drawable.x;
-    dy = old_origin.y - win->drawable.y;
-    REGION_TRANSLATE(win->drawable.pScreen, src_region, -dx, -dy);
-
-    REGION_INIT(win->drawable.pScreen, &dst_region, NullBox, 0);
-
-    REGION_INTERSECT(win->drawable.pScreen, &dst_region,
-                     &win->borderClip, src_region);
-#ifdef COMPOSITE
-    if (pixmap->screen_x || pixmap->screen_y)
-        REGION_TRANSLATE(win->drawable.pScreen, &dst_region,
-                         -pixmap->screen_x, -pixmap->screen_y);
-#endif
-
-    miCopyRegion(&pixmap->drawable, &pixmap->drawable,
-                 NULL, &dst_region, dx, dy, glamor_copy_n_to_n, 0, NULL);
-
-    REGION_UNINIT(win->drawable.pScreen, &dst_region);
-}
diff --git a/glamor/glamor_glyphs.c b/glamor/glamor_glyphs.c
index 42f5f65..ba7d342 100644
--- a/glamor/glamor_glyphs.c
+++ b/glamor/glamor_glyphs.c
@@ -448,9 +448,9 @@ glamor_glyph_cache_upload_glyph(ScreenPtr screen,
     box.y1 = y;
     box.x2 = x + glyph->info.width;
     box.y2 = y + glyph->info.height;
-    glamor_copy_n_to_n_nf(&scratch->drawable,
-                          &pCachePixmap->drawable, NULL,
-                          &box, 1, -x, -y, FALSE, FALSE, 0, NULL);
+    glamor_copy(&scratch->drawable,
+                &pCachePixmap->drawable, NULL,
+                &box, 1, -x, -y, FALSE, FALSE, 0, NULL);
     if (scratch != pGlyphPixmap)
         screen->DestroyPixmap(scratch);
 
diff --git a/glamor/glamor_largepixmap.c b/glamor/glamor_largepixmap.c
index b3a8d5d..5a4bec5 100644
--- a/glamor/glamor_largepixmap.c
+++ b/glamor/glamor_largepixmap.c
@@ -797,9 +797,9 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv,
         copy_box.y2 = temp_extent->y2 - temp_extent->y1;
         dx = temp_extent->x1;
         dy = temp_extent->y1;
-        glamor_copy_n_to_n(&priv->base.pixmap->drawable,
-                           &temp_pixmap->drawable,
-                           NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
+        glamor_copy(&priv->base.pixmap->drawable,
+                    &temp_pixmap->drawable,
+                    NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
 //              glamor_solid(temp_pixmap, 0, 0, temp_pixmap->drawable.width,
 //                             temp_pixmap->drawable.height, GXcopy, 0xffffffff, 0xff00);
     }
@@ -829,9 +829,10 @@ glamor_merge_clipped_regions(glamor_pixmap_private *pixmap_priv,
                        copy_box.x1, copy_box.y1, copy_box.x2,
                        copy_box.y2, dx, dy);
 
-                glamor_copy_n_to_n(&priv->base.pixmap->drawable,
-                                   &temp_pixmap->drawable,
-                                   NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
+                glamor_copy(&priv->base.pixmap->drawable,
+                            &temp_pixmap->drawable,
+                            NULL, &copy_box, 1, dx, dy, 0, 0, 0, NULL);
+
                 box++;
             }
         }
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 0af6092..1ae4e94 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -208,6 +208,7 @@ typedef struct glamor_screen_private {
     int has_map_buffer_range;
     int has_buffer_storage;
     int has_khr_debug;
+    int has_nv_texture_barrier;
     int max_fbo_size;
     int has_rw_pbo;
 
@@ -236,6 +237,10 @@ typedef struct glamor_screen_private {
     glamor_program      te_text_prog;
     glamor_program      image_text_prog;
 
+    /* glamor copy shaders */
+    glamor_program      copy_area_prog;
+    glamor_program      copy_plane_prog;
+
     /* vertext/elment_index buffer object for render */
     GLuint vbo, ebo;
     /** Next offset within the VBO that glamor_get_vbo_space() will use. */
@@ -619,15 +624,6 @@ glamor_pixmap_fbo *glamor_create_fbo_array(glamor_screen_private *glamor_priv,
                                            int flag, int block_w, int block_h,
                                            glamor_pixmap_private *);
 
-/* glamor_copyarea.c */
-RegionPtr
-
-glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
-                 int srcx, int srcy, int width, int height, int dstx, int dsty);
-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_core.c */
 void glamor_init_finish_access_shaders(ScreenPtr screen);
 void glamor_fini_finish_access_shaders(ScreenPtr screen);
@@ -931,11 +927,6 @@ void glamor_picture_format_fixup(PicturePtr picture,
 void glamor_add_traps(PicturePtr pPicture,
                       INT16 x_off, INT16 y_off, int ntrap, xTrap *traps);
 
-RegionPtr glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
-                            int srcx, int srcy, int w, int h,
-                            int dstx, int dsty,
-                            unsigned long bitPlane);
-
 /* glamor_text.c */
 int glamor_poly_text8(DrawablePtr pDrawable, GCPtr pGC,
                       int x, int y, int count, char *chars);
@@ -977,6 +968,29 @@ void
 glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
                  unsigned int format, unsigned long planeMask, char *d);
 
+/* glamor_copy.c */
+void
+glamor_copy(DrawablePtr src,
+            DrawablePtr dst,
+            GCPtr gc,
+            BoxPtr box,
+            int nbox,
+            int dx,
+            int dy,
+            Bool reverse,
+            Bool upsidedown,
+            Pixel bitplane,
+            void *closure);
+
+RegionPtr
+glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+                 int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+RegionPtr
+glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
+                  int srcx, int srcy, int width, int height, int dstx, int dsty,
+                  unsigned long bitplane);
+
 /* glamor_glyphblt.c */
 void glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
                             int x, int y, unsigned int nglyph,
diff --git a/glamor/glamor_program.c b/glamor/glamor_program.c
index 0f4d0f0..6ee6580 100644
--- a/glamor/glamor_program.c
+++ b/glamor/glamor_program.c
@@ -117,6 +117,11 @@ static glamor_location_var location_vars[] = {
         .location = glamor_program_location_font,
         .fs_vars = "uniform usampler2D font;\n",
     },
+    {
+        .location = glamor_program_location_bitplane,
+        .fs_vars = ("uniform uvec4 bitplane;\n"
+                    "uniform vec4 bitmul;\n"),
+    },
 };
 
 #define NUM_LOCATION_VARS       (sizeof location_vars / sizeof location_vars[0])
@@ -196,6 +201,8 @@ static const glamor_facet facet_null_fill = {
     .name = ""
 };
 
+#define DBG 0
+
 static GLint
 glamor_get_uniform(glamor_program               *prog,
                    glamor_program_location      location,
@@ -281,7 +288,6 @@ glamor_build_program(ScreenPtr          screen,
     if (!vs_prog_string || !fs_prog_string)
         goto fail;
 
-#define DBG 0
 #if DBG
     ErrorF("\nPrograms for %s %s\nVertex shader:\n\n%s\n\nFragment Shader:\n\n%s",
            prim->name, fill->name, vs_prog_string, fs_prog_string);
@@ -318,6 +324,8 @@ glamor_build_program(ScreenPtr          screen,
     prog->fill_offset_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_offset");
     prog->fill_size_uniform = glamor_get_uniform(prog, glamor_program_location_fill, "fill_size");
     prog->font_uniform = glamor_get_uniform(prog, glamor_program_location_font, "font");
+    prog->bitplane_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitplane");
+    prog->bitmul_uniform = glamor_get_uniform(prog, glamor_program_location_bitplane, "bitmul");
 
     if (glGetError() != GL_NO_ERROR)
         goto fail;
diff --git a/glamor/glamor_program.h b/glamor/glamor_program.h
index 88efc35..118f978 100644
--- a/glamor/glamor_program.h
+++ b/glamor/glamor_program.h
@@ -29,6 +29,7 @@ typedef enum {
     glamor_program_location_bg = 2,
     glamor_program_location_fill = 4,
     glamor_program_location_font = 8,
+    glamor_program_location_bitplane = 16,
 } glamor_program_location;
 
 typedef enum {
@@ -61,6 +62,8 @@ struct _glamor_program {
     GLint                       fill_size_uniform;
     GLint                       fill_offset_uniform;
     GLint                       font_uniform;
+    GLint                       bitplane_uniform;
+    GLint                       bitmul_uniform;
     glamor_program_location     locations;
     glamor_program_flag         flags;
     glamor_use                  prim_use;
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 8952023..6da38da 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -651,11 +651,12 @@ glamor_composite_with_copy(CARD8 op,
         if (region->extents.y2 + y_source - y_dest > source->pDrawable->height)
             goto cleanup_region;
     }
-    ret = glamor_copy_n_to_n_nf(source->pDrawable,
-                                dest->pDrawable, NULL,
-                                RegionRects(region), RegionNumRects(region),
-                                x_source - x_dest, y_source - y_dest,
-                                FALSE, FALSE, 0, NULL);
+    glamor_copy(source->pDrawable,
+                dest->pDrawable, NULL,
+                RegionRects(region), RegionNumRects(region),
+                x_source - x_dest, y_source - y_dest,
+                FALSE, FALSE, 0, NULL);
+    ret = TRUE;
  cleanup_region:
     return ret;
 }
commit 0e08a79599c773f77c0667d557376a5ccee3f89c
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Apr 2 14:05:35 2014 -0700

    glamor: Directly reference the private key records
    
    There's no reason to use a pointer here, it just wastes time.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 6aaf1b4..ac23d52 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -35,10 +35,8 @@
 
 #include "glamor_priv.h"
 
-static DevPrivateKeyRec glamor_screen_private_key_index;
-DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index;
-static DevPrivateKeyRec glamor_pixmap_private_key_index;
-DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index;
+DevPrivateKeyRec glamor_screen_private_key;
+DevPrivateKeyRec glamor_pixmap_private_key;
 
 /**
  * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@@ -68,7 +66,7 @@ glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type)
         glamor_get_screen_private(pixmap->drawable.pScreen);
 
     pixmap_priv = dixLookupPrivate(&pixmap->devPrivates,
-                                   glamor_pixmap_private_key);
+                                   &glamor_pixmap_private_key);
     if (pixmap_priv == NULL) {
         pixmap_priv = calloc(sizeof(*pixmap_priv), 1);
         glamor_set_pixmap_private(pixmap, pixmap_priv);
@@ -335,7 +333,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
     else
         glamor_priv->yInverted = FALSE;
 
-    if (!dixRegisterPrivateKey(glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
+    if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) {
         LogMessage(X_WARNING,
                    "glamor%d: Failed to allocate screen private\n",
                    screen->myNum);
@@ -344,7 +342,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 
     glamor_set_screen_private(screen, glamor_priv);
 
-    if (!dixRegisterPrivateKey(glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
+    if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, 0)) {
         LogMessage(X_WARNING,
                    "glamor%d: Failed to allocate pixmap private\n",
                    screen->myNum);
@@ -559,7 +557,7 @@ glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv)
     glamor_pixmap_private *old_priv;
     glamor_pixmap_fbo *fbo;
 
-    old_priv = dixGetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key);
+    old_priv = dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key);
 
     if (priv) {
         assert(old_priv == NULL);
@@ -572,7 +570,7 @@ glamor_set_pixmap_private(PixmapPtr pixmap, glamor_pixmap_private *priv)
         free(old_priv);
     }
 
-    dixSetPrivate(&pixmap->devPrivates, glamor_pixmap_private_key, priv);
+    dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key, priv);
 }
 
 Bool
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 531d25d..0af6092 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -548,19 +548,20 @@ typedef enum glamor_pixmap_status {
     GLAMOR_UPLOAD_FAILED
 } glamor_pixmap_status_t;
 
-extern DevPrivateKey glamor_screen_private_key;
-extern DevPrivateKey glamor_pixmap_private_key;
+extern DevPrivateKeyRec glamor_screen_private_key;
+extern DevPrivateKeyRec glamor_pixmap_private_key;
+
 static inline glamor_screen_private *
 glamor_get_screen_private(ScreenPtr screen)
 {
     return (glamor_screen_private *)
-        dixLookupPrivate(&screen->devPrivates, glamor_screen_private_key);
+        dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key);
 }
 
 static inline void
 glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv)
 {
-    dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, priv);
+    dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv);
 }
 
 static inline glamor_pixmap_private *
@@ -568,11 +569,11 @@ glamor_get_pixmap_private(PixmapPtr pixmap)
 {
     glamor_pixmap_private *priv;
 
-    priv = dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key);
+    priv = dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_private_key);
     if (!priv) {
         glamor_set_pixmap_type(pixmap, GLAMOR_MEMORY);
         priv = dixLookupPrivate(&pixmap->devPrivates,
-                                glamor_pixmap_private_key);
+                                &glamor_pixmap_private_key);
     }
     return priv;
 }
commit 15e4d14dfae054c026b7e965ac33985e5cf6a168
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 15 13:27:14 2014 -0700

    glamor: Replace fallback preparation code
    
    These offer a simpler and more efficient means for temporarily
    transitioning to CPU-accessible memory for fallback implementations.
    
    v2: Do not attempt fallbacks with GLAMOR_DRM_ONLY pixmaps
    
        glamor cannot transfer pixels for GLAMOR_DRM_ONLY pixmaps using
        glReadPixels and glTexSubImage2D, and so there's no way to perform
        fallback operations with these pixmaps.
    
    v3: Clear ->pbo field when deleting the PBO.  Otherwise, we'd reuse
        the old name next time we fall back on the pixmap, which would
        potentially conflict with some other pixmap that genned a new
        name, or just do a lazy allocation of the name (compat GL context,
        like we currently use) or error out (core GL context, like we hope
        to use some day).  Also, style fixes.  Changes by anholt, acked by
        keithp.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index bde58b6..cb81872 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -21,6 +21,8 @@ libglamor_la_SOURCES = \
 	glamor_image.c \
 	glamor_render.c \
 	glamor_gradient.c \
+	glamor_prepare.c \
+	glamor_prepare.h \
 	glamor_program.c \
 	glamor_program.h \
 	glamor_rects.c \
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 08f6ba1..6aaf1b4 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -397,6 +397,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         }
     }
 
+    glamor_priv->has_rw_pbo = FALSE;
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
+        glamor_priv->has_rw_pbo = TRUE;
+
     glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug");
     glamor_priv->has_pack_invert =
         epoxy_has_gl_extension("GL_MESA_pack_invert");
diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c
index b349437..ffb6eba 100644
--- a/glamor/glamor_core.c
+++ b/glamor/glamor_core.c
@@ -114,27 +114,6 @@ glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...)
     }
 }
 
-Bool
-glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
-{
-    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-
-    if (pixmap->devPrivate.ptr) {
-        /* Already mapped, nothing needs to be done.  Note that we
-         * aren't allowing promotion from RO to RW, because it would
-         * require re-mapping the PBO.
-         */
-        assert(!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) ||
-               access == GLAMOR_ACCESS_RO ||
-               pixmap_priv->base.map_access == GLAMOR_ACCESS_RW);
-        return TRUE;
-    }
-    pixmap_priv->base.map_access = access;
-
-    return glamor_download_pixmap_to_cpu(pixmap, access);
-}
-
 /*
  *  When downloading a unsupported color format to CPU memory,
     we need to shuffle the color elements and then use a supported
@@ -313,91 +292,6 @@ glamor_fini_finish_access_shaders(ScreenPtr screen)
     glDeleteProgram(glamor_priv->finish_access_prog[1]);
 }
 
-void
-glamor_finish_access(DrawablePtr drawable)
-{
-    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(drawable->pScreen);
-
-    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO_DOWNLOADED(pixmap_priv))
-        return;
-
-    /* If we are doing a series of unmaps from a nested map, we're
-     * done.  None of the callers do any rendering to maps after
-     * starting an unmap sequence, so we don't need to delay until the
-     * last nested unmap.
-     */
-    if (!pixmap->devPrivate.ptr)
-        return;
-
-    if (pixmap_priv->base.map_access == GLAMOR_ACCESS_RW) {
-        glamor_restore_pixmap_to_texture(pixmap);
-    }
-
-    if (pixmap_priv->base.fbo->pbo != 0 && pixmap_priv->base.fbo->pbo_valid) {
-        assert(glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP);
-
-        glamor_make_current(glamor_priv);
-        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-        glDeleteBuffers(1, &pixmap_priv->base.fbo->pbo);
-
-        pixmap_priv->base.fbo->pbo_valid = FALSE;
-        pixmap_priv->base.fbo->pbo = 0;
-    }
-    else {
-        free(pixmap->devPrivate.ptr);
-    }
-
-    if (pixmap_priv->type == GLAMOR_TEXTURE_DRM)
-        pixmap->devKind = pixmap_priv->base.drm_stride;
-
-    if (pixmap_priv->base.gl_fbo == GLAMOR_FBO_DOWNLOADED)
-        pixmap_priv->base.gl_fbo = GLAMOR_FBO_NORMAL;
-
-    pixmap->devPrivate.ptr = NULL;
-}
-
-/**
- * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the
- * current fill style.
- *
- * Solid doesn't use an extra pixmap source, so we don't worry about them.
- * Stippled/OpaqueStippled are 1bpp and can be in fb, so we should worry
- * about them.
- */
-Bool
-glamor_prepare_access_gc(GCPtr gc)
-{
-    if (gc->stipple) {
-        if (!glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO))
-            return FALSE;
-    }
-    if (gc->fillStyle == FillTiled) {
-        if (!glamor_prepare_access(&gc->tile.pixmap->drawable,
-                                   GLAMOR_ACCESS_RO)) {
-            if (gc->stipple)
-                glamor_finish_access(&gc->stipple->drawable);
-            return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-/**
- * Finishes access to the tile in the GC, if used.
- */
-void
-glamor_finish_access_gc(GCPtr gc)
-{
-    if (gc->fillStyle == FillTiled)
-        glamor_finish_access(&gc->tile.pixmap->drawable);
-    if (gc->stipple)
-        glamor_finish_access(&gc->stipple->drawable);
-}
-
 Bool
 glamor_stipple(PixmapPtr pixmap, PixmapPtr stipple,
                int x, int y, int width, int height,
diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c
index 5fdc5f9..cbbc194 100644
--- a/glamor/glamor_picture.c
+++ b/glamor/glamor_picture.c
@@ -45,24 +45,6 @@ glamor_upload_picture_to_texture(PicturePtr picture)
     return glamor_upload_pixmap_to_texture(pixmap);
 }
 
-Bool
-glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
-{
-    if (!picture || !picture->pDrawable)
-        return TRUE;
-
-    return glamor_prepare_access(picture->pDrawable, access);
-}
-
-void
-glamor_finish_access_picture(PicturePtr picture)
-{
-    if (!picture || !picture->pDrawable)
-        return;
-
-    glamor_finish_access(picture->pDrawable);
-}
-
 /* 
  * We should already have drawable attached to it, if it has one.
  * Then set the attached pixmap to is_picture format, and set
diff --git a/glamor/glamor_prepare.c b/glamor/glamor_prepare.c
new file mode 100644
index 0000000..561c55d
--- /dev/null
+++ b/glamor/glamor_prepare.c
@@ -0,0 +1,274 @@
+/*
+ * 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_prepare.h"
+#include "glamor_transfer.h"
+
+/*
+ * Make a pixmap ready to draw with fb by
+ * creating a PBO large enough for the whole object
+ * and downloading all of the FBOs into it.
+ */
+
+static Bool
+glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
+    int                         gl_access, gl_usage;
+    RegionRec                   region;
+
+    if (priv->type == GLAMOR_DRM_ONLY)
+        return FALSE;
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
+        return TRUE;
+
+    RegionInit(&region, box, 1);
+
+    /* See if it's already mapped */
+    if (pixmap->devPrivate.ptr) {
+        /*
+         * Someone else has mapped this pixmap;
+         * we'll assume that it's directly mapped
+         * by a lower level driver
+         */
+        if (!priv->base.prepared)
+            return TRUE;
+
+        /* In X, multiple Drawables can be stored in the same Pixmap (such as
+         * each individual window in a non-composited screen pixmap, or the
+         * reparented window contents inside the window-manager-decorated window
+         * pixmap on a composited screen).
+         *
+         * As a result, when doing a series of mappings for a fallback, we may
+         * need to add more boxes to the set of data we've downloaded, as we go.
+         */
+        RegionSubtract(&region, &region, &priv->base.prepare_region);
+        if (!RegionNotEmpty(&region))
+            return TRUE;
+
+        if (access == GLAMOR_ACCESS_RW)
+            FatalError("attempt to remap buffer as writable");
+
+        if (priv->base.pbo) {
+            glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo);
+            glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+            pixmap->devPrivate.ptr = NULL;
+        }
+    } else {
+        RegionInit(&priv->base.prepare_region, box, 1);
+
+        if (glamor_priv->has_rw_pbo) {
+            if (priv->base.pbo == 0)
+                glGenBuffers(1, &priv->base.pbo);
+
+            if (access == GLAMOR_ACCESS_RW)
+                gl_usage = GL_DYNAMIC_DRAW;
+            else
+                gl_usage = GL_STREAM_READ;
+
+            glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo);
+            glBufferData(GL_PIXEL_PACK_BUFFER,
+                         pixmap->devKind * pixmap->drawable.height, NULL,
+                         gl_usage);
+        } else {
+            pixmap->devPrivate.ptr = malloc(pixmap->devKind *
+                                            pixmap->drawable.height);
+            if (!pixmap->devPrivate.ptr)
+                return FALSE;
+        }
+        priv->base.map_access = access;
+    }
+
+    glamor_download_boxes(pixmap, RegionRects(&region), RegionNumRects(&region),
+                          0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
+
+    RegionUninit(&region);
+
+    if (glamor_priv->has_rw_pbo) {
+        if (priv->base.map_access == GLAMOR_ACCESS_RW)
+            gl_access = GL_READ_WRITE;
+        else
+            gl_access = GL_READ_ONLY;
+
+        pixmap->devPrivate.ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
+        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    }
+
+    priv->base.prepared = TRUE;
+    return TRUE;
+}
+
+/*
+ * When we're done with the drawable, unmap the PBO, reupload
+ * if we were writing to it and then unbind it to release the memory
+ */
+
+static void
+glamor_fini_pixmap(PixmapPtr pixmap)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
+
+    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
+        return;
+
+    if (!priv->base.prepared)
+        return;
+
+    if (glamor_priv->has_rw_pbo) {
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->base.pbo);
+        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+        pixmap->devPrivate.ptr = NULL;
+    }
+
+    if (priv->base.map_access == GLAMOR_ACCESS_RW) {
+        glamor_upload_boxes(pixmap,
+                            RegionRects(&priv->base.prepare_region),
+                            RegionNumRects(&priv->base.prepare_region),
+                            0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
+    }
+
+    RegionUninit(&priv->base.prepare_region);
+
+    if (glamor_priv->has_rw_pbo) {
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+        glDeleteBuffers(1, &priv->base.pbo);
+        priv->base.pbo = 0;
+    } else {
+        free(pixmap->devPrivate.ptr);
+        pixmap->devPrivate.ptr = NULL;
+    }
+
+    priv->base.prepared = FALSE;
+}
+
+Bool
+glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    BoxRec box;
+    int off_x, off_y;
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+    box.x1 = drawable->x + off_x;
+    box.x2 = box.x1 + drawable->width;
+    box.y1 = drawable->y + off_y;
+    box.y2 = box.y1 + drawable->height;
+    return glamor_prep_pixmap_box(pixmap, access, &box);
+}
+
+Bool
+glamor_prepare_access_box(DrawablePtr drawable, glamor_access_t access,
+                         int x, int y, int w, int h)
+{
+    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+    BoxRec box;
+    int off_x, off_y;
+
+    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+    box.x1 = drawable->x + x + off_x;
+    box.x2 = box.x1 + w;
+    box.y1 = drawable->y + y + off_y;
+    box.y2 = box.y1 + h;
+    return glamor_prep_pixmap_box(pixmap, access, &box);
+}
+
+void
+glamor_finish_access(DrawablePtr drawable)
+{
+    glamor_fini_pixmap(glamor_get_drawable_pixmap(drawable));
+}
+
+/*
+ * Make a picture ready to use with fb.
+ */
+
+Bool
+glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
+{
+    if (!picture || !picture->pDrawable)
+        return TRUE;
+
+    return glamor_prepare_access(picture->pDrawable, access);
+}
+
+Bool
+glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access,
+                        int x, int y, int w, int h)
+{
+    if (!picture || !picture->pDrawable)
+        return TRUE;
+    return glamor_prepare_access_box(picture->pDrawable, access,
+                                    x, y, w, h);
+}
+
+void
+glamor_finish_access_picture(PicturePtr picture)
+{
+    if (!picture || !picture->pDrawable)
+        return;
+
+    glamor_finish_access(picture->pDrawable);
+}
+
+/*
+ * Make a GC ready to use with fb. This just
+ * means making sure the appropriate fill pixmap is
+ * in CPU memory again
+ */
+
+Bool
+glamor_prepare_access_gc(GCPtr gc)
+{
+    switch (gc->fillStyle) {
+    case FillTiled:
+        return glamor_prepare_access(&gc->tile.pixmap->drawable,
+                                     GLAMOR_ACCESS_RO);
+    case FillStippled:
+    case FillOpaqueStippled:
+        return glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO);
+    }
+    return TRUE;
+}
+
+/*
+ * Free any temporary CPU pixmaps for the GC
+ */
+void
+glamor_finish_access_gc(GCPtr gc)
+{
+    switch (gc->fillStyle) {
+    case FillTiled:
+        glamor_finish_access(&gc->tile.pixmap->drawable);
+        break;
+    case FillStippled:
+    case FillOpaqueStippled:
+        glamor_finish_access(&gc->stipple->drawable);
+        break;
+    }
+}
diff --git a/glamor/glamor_prepare.h b/glamor/glamor_prepare.h
new file mode 100644
index 0000000..85fa795
--- /dev/null
+++ b/glamor/glamor_prepare.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _GLAMOR_PREPARE_H_
+#define _GLAMOR_PREPARE_H_
+
+Bool
+glamor_prepare_access(DrawablePtr drawable, glamor_access_t access);
+
+Bool
+glamor_prepare_access_box(DrawablePtr drawable, glamor_access_t access,
+                         int x, int y, int w, int h);
+
+void
+glamor_finish_access(DrawablePtr drawable);
+
+Bool
+glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access);
+
+Bool
+glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access,
+                        int x, int y, int w, int h);
+
+void
+glamor_finish_access_picture(PicturePtr picture);
+
+Bool
+glamor_prepare_access_gc(GCPtr gc);
+
+void
+glamor_finish_access_gc(GCPtr gc);
+
+#endif /* _GLAMOR_PREPARE_H_ */
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index c56c559..531d25d 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -209,6 +209,7 @@ typedef struct glamor_screen_private {
     int has_buffer_storage;
     int has_khr_debug;
     int max_fbo_size;
+    int has_rw_pbo;
 
     struct xorg_list
         fbo_cache[CACHE_FORMAT_COUNT][CACHE_BUCKET_WCOUNT][CACHE_BUCKET_HCOUNT];
@@ -430,6 +431,9 @@ typedef struct glamor_pixmap_private_base {
     int drm_stride;
     glamor_screen_private *glamor_priv;
     PicturePtr picture;
+    GLuint pbo;
+    RegionRec prepare_region;
+    Bool prepared;
 #if GLAMOR_HAS_GBM
     EGLImageKHR image;
 #endif
@@ -624,14 +628,9 @@ void glamor_copy_n_to_n(DrawablePtr src, DrawablePtr dst, GCPtr gc,
                         Bool upsidedown, Pixel bitplane, void *closure);
 
 /* glamor_core.c */
-Bool glamor_prepare_access(DrawablePtr drawable, glamor_access_t access);
-void glamor_finish_access(DrawablePtr drawable);
-Bool glamor_prepare_access_window(WindowPtr window);
-void glamor_finish_access_window(WindowPtr window);
-Bool glamor_prepare_access_gc(GCPtr gc);
-void glamor_finish_access_gc(GCPtr gc);
 void glamor_init_finish_access_shaders(ScreenPtr screen);
 void glamor_fini_finish_access_shaders(ScreenPtr screen);
+
 const Bool glamor_get_drawable_location(const DrawablePtr drawable);
 void glamor_get_drawable_deltas(DrawablePtr drawable, PixmapPtr pixmap,
                                 int *x, int *y);
@@ -919,10 +918,6 @@ int glamor_create_picture(PicturePtr picture);
 
 void glamor_set_window_pixmap(WindowPtr pWindow, PixmapPtr pPixmap);
 
-Bool glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access);
-
-void glamor_finish_access_picture(PicturePtr picture);
-
 void glamor_destroy_picture(PicturePtr picture);
 
 /* fixup a fbo to the exact size as the pixmap. */
diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c
index 5a7a238..8952023 100644
--- a/glamor/glamor_render.c
+++ b/glamor/glamor_render.c
@@ -1586,15 +1586,6 @@ _glamor_composite(CARD8 op,
     RegionRec region;
     BoxPtr extent;
     int nbox, ok = FALSE;
-    PixmapPtr sub_dest_pixmap = NULL;
-    PixmapPtr sub_source_pixmap = NULL;
-    PixmapPtr sub_mask_pixmap = NULL;
-    int dest_x_off, dest_y_off, saved_dest_x, saved_dest_y;
-    int source_x_off, source_y_off, saved_source_x, saved_source_y;
-    int mask_x_off, mask_y_off, saved_mask_x, saved_mask_y;
-    DrawablePtr saved_dest_drawable;
-    DrawablePtr saved_source_drawable;
-    DrawablePtr saved_mask_drawable;
     int force_clip = 0;
 
     dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
@@ -1737,34 +1728,13 @@ _glamor_composite(CARD8 op,
          dest->pDrawable->width, dest->pDrawable->height,
          glamor_get_picture_location(dest));
 
-#define GET_SUB_PICTURE(p, access)		do {					\
-	glamor_get_drawable_deltas(p->pDrawable, p ##_pixmap,				\
-				   & p ##_x_off, & p ##_y_off);				\
-	sub_ ##p ##_pixmap = glamor_get_sub_pixmap(p ##_pixmap,				\
-					      x_ ##p + p ##_x_off + p->pDrawable->x,	\
-					      y_ ##p + p ##_y_off + p->pDrawable->y,	\
-					      width, height, access);			\
-	if (sub_ ##p ##_pixmap != NULL) {						\
-		saved_ ##p ##_drawable = p->pDrawable;					\
-		saved_ ##p ##_x = x_ ##p;						\
-		saved_ ##p ##_y = y_ ##p;						\
-		if (p->pCompositeClip)							\
-			pixman_region_translate (p->pCompositeClip,			\
-						 -p->pDrawable->x - x_ ##p,		\
-						 -p->pDrawable->y - y_ ##p);		\
-		p->pDrawable = &sub_ ##p ##_pixmap->drawable;				\
-		x_ ##p = 0;								\
-		y_ ##p = 0;								\
-	} } while(0)
-    GET_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
-    if (source->pDrawable && !source->transform)
-        GET_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
-    if (mask && mask->pDrawable && !mask->transform)
-        GET_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
-
-    if (glamor_prepare_access_picture(dest, GLAMOR_ACCESS_RW) &&
-        glamor_prepare_access_picture(source, GLAMOR_ACCESS_RO) &&
-        glamor_prepare_access_picture(mask, GLAMOR_ACCESS_RO)) {
+    if (glamor_prepare_access_picture_box(dest, GLAMOR_ACCESS_RW,
+                                          x_dest, y_dest, width, height) &&
+        glamor_prepare_access_picture_box(source, GLAMOR_ACCESS_RO,
+                                          x_source, y_source, width, height) &&
+        glamor_prepare_access_picture_box(mask, GLAMOR_ACCESS_RO,
+                                          x_mask, y_mask, width, height))
+    {
         fbComposite(op,
                     source, mask, dest,
                     x_source, y_source,
@@ -1774,25 +1744,6 @@ _glamor_composite(CARD8 op,
     glamor_finish_access_picture(source);
     glamor_finish_access_picture(dest);
 
-#define PUT_SUB_PICTURE(p, access)		do {				\
-	if (sub_ ##p ##_pixmap != NULL) {					\
-		x_ ##p = saved_ ##p ##_x;					\
-		y_ ##p = saved_ ##p ##_y;					\
-		p->pDrawable = saved_ ##p ##_drawable;				\
-		if (p->pCompositeClip)						\
-			pixman_region_translate (p->pCompositeClip,		\
-						 p->pDrawable->x + x_ ##p,	\
-						 p->pDrawable->y + y_ ##p);	\
-		glamor_put_sub_pixmap(sub_ ##p ##_pixmap, p ##_pixmap,		\
-				      x_ ##p + p ##_x_off + p->pDrawable->x,	\
-				      y_ ##p + p ##_y_off + p->pDrawable->y,	\
-				      width, height, access);			\
-	}} while(0)
-    if (mask && mask->pDrawable)
-        PUT_SUB_PICTURE(mask, GLAMOR_ACCESS_RO);
-    if (source->pDrawable)
-        PUT_SUB_PICTURE(source, GLAMOR_ACCESS_RO);
-    PUT_SUB_PICTURE(dest, GLAMOR_ACCESS_RW);
  done:
     return ret;
 }
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index 4c1581e..5a568f1 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -32,6 +32,8 @@
 #ifndef __GLAMOR_UTILS_H__
 #define __GLAMOR_UTILS_H__
 
+#include "glamor_prepare.h"
+
 #define v_from_x_coord_x(_xscale_, _x_)          ( 2 * (_x_) * (_xscale_) - 1.0)
 #define v_from_x_coord_y(_yscale_, _y_)          (-2 * (_y_) * (_yscale_) + 1.0)
 #define v_from_x_coord_y_inverted(_yscale_, _y_) (2 * (_y_) * (_yscale_) - 1.0)
commit 3ac481c9dac591ffc33812ab047fc793d8a43d4f
Author: Keith Packard <keithp at keithp.com>
Date:   Wed May 7 10:31:16 2014 -0700

    mi: Draw multiple lines in one FillSpans call in miZeroLine
    
    miZeroLine allocates enough space to draw a line spanning the entire
    width/height of the target drawable. When drawing multiple shorter
    lines, this leaves most of the space in that buffer unfilled. Let
    multiple lines be drawn into the buffer if there is plenty of space.
    
    Speeds up glamor fallback zero-width lines:
    
    Before
        6000000 trep @   0.0020 msec (508000.0/sec): 1-pixel line
        6000000 trep @   0.0020 msec (492000.0/sec): 10-pixel line
        6000000 trep @   0.0023 msec (427000.0/sec): 100-pixel line
        4000000 trep @   0.0035 msec (282000.0/sec): 500-pixel line
    
    After:
      600000000 trep @   0.0000 msec (43400000.0/sec): 1-pixel line
      140000000 trep @   0.0001 msec (13000000.0/sec): 10-pixel line
       16000000 trep @   0.0008 msec (1300000.0/sec): 100-pixel line
        4000000 trep @   0.0038 msec (261000.0/sec): 500-pixel line
    
    (500 pixel lines do not change in performance because the buffer can
    only one one of them.)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/mi/mizerline.c b/mi/mizerline.c
index 90798db..f30e012 100644
--- a/mi/mizerline.c
+++ b/mi/mizerline.c
@@ -179,14 +179,6 @@ miZeroLine(DrawablePtr pDraw, GCPtr pGC, int mode,      /* Origin or Previous */
     MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
 
     while (--npt > 0) {
-        if (Nspans > 0)
-            (*pGC->ops->FillSpans) (pDraw, pGC, Nspans, pspanInit,
-                                    pwidthInit, FALSE);
-        Nspans = 0;
-        new_span = TRUE;
-        spans = pspanInit - 1;
-        widths = pwidthInit - 1;
-
         x1 = x2;
         y1 = y2;
         oc1 = oc2;
@@ -208,6 +200,14 @@ miZeroLine(DrawablePtr pDraw, GCPtr pGC, int mode,      /* Origin or Previous */
 
         CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
 
+        if (ady + 1 > (list_len - Nspans)) {
+            (*pGC->ops->FillSpans) (pDraw, pGC, Nspans, pspanInit,
+                                    pwidthInit, FALSE);
+            Nspans = 0;
+            spans = pspanInit - 1;
+            widths = pwidthInit - 1;
+        }
+        new_span = TRUE;
         if (adx > ady) {
             e1 = ady << 1;
             e2 = e1 - (adx << 1);
commit ea678a73c5688f73071d5581b6406808b7a0230f
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Apr 25 22:43:51 2014 -0700

    mi: Fill spans for multiple arcs in miPolyFillArc
    
    This allocates span data for multiple arcs and draws the
    whole set in one call, rather than doing them one at a time. For
    modern hardware, this is a significant performance improvement.
    
    v2: Limit the number of spans per buffer to 4M to avoid
        integer overflow in computing the malloc size.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/mi/mifillarc.c b/mi/mifillarc.c
index 337343d..08484d7 100644
--- a/mi/mifillarc.c
+++ b/mi/mifillarc.c
@@ -476,26 +476,16 @@ miFillArcSliceSetup(xArc * arc, miArcSliceRec * slice, GCPtr pGC)
 	*wids++ = slw; \
     }
 
-static void
-miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
+static int
+miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
 {
     int x, y, e;
     int yk, xk, ym, xm, dx, dy, xorg, yorg;
     int slw;
     miFillArcRec info;
-    DDXPointPtr points;
     DDXPointPtr pts;
-    int *widths;
     int *wids;
 
-    points = malloc(sizeof(DDXPointRec) * arc->height);
-    if (!points)
-        return;
-    widths = malloc(sizeof(int) * arc->height);
-    if (!widths) {
-        free(points);
-        return;
-    }
     miFillArcSetup(arc, &info);
     MIFILLARCSETUP();
     if (pGC->miTranslate) {
@@ -508,31 +498,19 @@ miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
         MIFILLARCSTEP(slw);
         ADDSPANS();
     }
-    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
-    free(widths);
-    free(points);
+    return pts - points;
 }
 
-static void
-miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
+static int
+miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
 {
     int x, y;
     int xorg, yorg, dx, dy, slw;
     double e, yk, xk, ym, xm;
     miFillArcDRec info;
-    DDXPointPtr points;
     DDXPointPtr pts;
-    int *widths;
     int *wids;
 
-    points = malloc(sizeof(DDXPointRec) * arc->height);
-    if (!points)
-        return;
-    widths = malloc(sizeof(int) * arc->height);
-    if (!widths) {
-        free(points);
-        return;
-    }
     miFillArcDSetup(arc, &info);
     MIFILLARCSETUP();
     if (pGC->miTranslate) {
@@ -545,9 +523,7 @@ miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
         MIFILLARCSTEP(slw);
         ADDSPANS();
     }
-    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
-    free(widths);
-    free(points);
+    return pts - points;
 }
 
 #define ADDSPAN(l,r) \
@@ -572,17 +548,15 @@ miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
 	ADDSPAN(xl, xc); \
     }
 
-static void
-miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
+static int
+miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
 {
     int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
     int x, y, e;
     miFillArcRec info;
     miArcSliceRec slice;
     int ya, xl, xr, xc;
-    DDXPointPtr points;
     DDXPointPtr pts;
-    int *widths;
     int *wids;
 
     miFillArcSetup(arc, &info);
@@ -591,14 +565,6 @@ miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
     slw = arc->height;
     if (slice.flip_top || slice.flip_bot)
         slw += (arc->height >> 1) + 1;
-    points = malloc(sizeof(DDXPointRec) * slw);
-    if (!points)
-        return;
-    widths = malloc(sizeof(int) * slw);
-    if (!widths) {
-        free(points);
-        return;
-    }
     if (pGC->miTranslate) {
         xorg += pDraw->x;
         yorg += pDraw->y;
@@ -622,13 +588,11 @@ miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
             ADDSLICESPANS(slice.flip_bot);
         }
     }
-    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
-    free(widths);
-    free(points);
+    return pts - points;
 }
 
-static void
-miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
+static int
+miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
 {
     int x, y;
     int dx, dy, xorg, yorg, slw;
@@ -636,9 +600,7 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
     miFillArcDRec info;
     miArcSliceRec slice;
     int ya, xl, xr, xc;
-    DDXPointPtr points;
     DDXPointPtr pts;
-    int *widths;
     int *wids;
 
     miFillArcDSetup(arc, &info);
@@ -647,14 +609,6 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
     slw = arc->height;
     if (slice.flip_top || slice.flip_bot)
         slw += (arc->height >> 1) + 1;
-    points = malloc(sizeof(DDXPointRec) * slw);
-    if (!points)
-        return;
-    widths = malloc(sizeof(int) * slw);
-    if (!widths) {
-        free(points);
-        return;
-    }
     if (pGC->miTranslate) {
         xorg += pDraw->x;
         yorg += pDraw->y;
@@ -678,35 +632,69 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
             ADDSLICESPANS(slice.flip_bot);
         }
     }
-    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
-    free(widths);
-    free(points);
+    return pts - points;
 }
 
 /* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
  * Since we don't have to worry about overlapping segments, we can just
  * fill each arc as it comes.
  */
+
+/* Limit the number of spans in a single draw request to avoid integer
+ * overflow in the computation of the span buffer size.
+ */
+#define MAX_SPANS_PER_LOOP      (4 * 1024 * 1024)
+
 void
-miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
+miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs_all, xArc * parcs)
 {
-    int i;
-    xArc *arc;
-
-    for (i = narcs, arc = parcs; --i >= 0; arc++) {
-        if (miFillArcEmpty(arc))
-            continue;
-        if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) {
-            if (miCanFillArc(arc))
-                miFillEllipseI(pDraw, pGC, arc);
-            else
-                miFillEllipseD(pDraw, pGC, arc);
-        }
-        else {
-            if (miCanFillArc(arc))
-                miFillArcSliceI(pDraw, pGC, arc);
-            else
-                miFillArcSliceD(pDraw, pGC, arc);
-        }
+    while (narcs_all > 0) {
+        int narcs;
+        int i;
+        xArc *arc;
+        int nspans = 0;
+        DDXPointPtr pts, points;
+        int *wids, *widths;
+        int n;
+
+        for (narcs = 0, arc = parcs; narcs < narcs_all; narcs++, arc++) {
+            if (narcs && nspans + arc->height > MAX_SPANS_PER_LOOP)
+                break;
+            nspans += arc->height;
+        }
+
+        pts = points = malloc (sizeof (DDXPointRec) * nspans +
+                               sizeof(int) * nspans);
+        if (points) {
+            wids = widths = (int *) (points + nspans);
+
+            for (i = 0, arc = parcs; i < narcs; arc++, i++) {
+                if (miFillArcEmpty(arc))
+                    continue;
+                if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
+                {
+                    if (miCanFillArc(arc))
+                        n = miFillEllipseI(pDraw, pGC, arc, pts, wids);
+                    else
+                        n = miFillEllipseD(pDraw, pGC, arc, pts, wids);
+                }
+                else
+                {
+                    if (miCanFillArc(arc))
+                        n = miFillArcSliceI(pDraw, pGC, arc, pts, wids);
+                    else
+                        n = miFillArcSliceD(pDraw, pGC, arc, pts, wids);
+                }
+                pts += n;
+                wids += n;
+            }
+            nspans = pts - points;
+            if (nspans)
+                (*pGC->ops->FillSpans) (pDraw, pGC, nspans, points,
+                                        widths, FALSE);
+            free (points);
+        }
+        parcs += narcs;
+        narcs_all -= narcs;
     }
 }
commit a7fce36affb8211990e5b4956adea4d75f0e73c9
Author: Keith Packard <keithp at keithp.com>
Date:   Wed May 7 09:58:26 2014 -0700

    mi: Make miPolyArc draw fast zero-width when possible
    
    Instead of forcing drivers to figure out when to call miZeroPolyArc,
    have miPolyArc call that when possible.
    
    This involved renaming the existing miPolyArc call to miWideArc and
    creating a new miPolyArc wrapper function as miZeroPolyArc falls back
    to miWideArc when the arc is too large to be drawn with the zero-width
    code (ellipses larger than 800x800).
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/mi/mi.h b/mi/mi.h
index b8a4f05..cacb2e0 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -67,6 +67,11 @@ typedef struct _miDash *miDashPtr;
 
 /* miarc.c */
 
+extern _X_EXPORT void miWideArc(DrawablePtr pDraw,
+                                GCPtr pGC,
+                                int narcs,
+                                xArc * parcs);
+
 extern _X_EXPORT void miPolyArc(DrawablePtr /*pDraw */ ,
                                 GCPtr /*pGC */ ,
                                 int /*narcs */ ,
diff --git a/mi/miarc.c b/mi/miarc.c
index 0f56c7d..e55108a 100644
--- a/mi/miarc.c
+++ b/mi/miarc.c
@@ -886,7 +886,7 @@ miFillWideEllipse(DrawablePtr pDraw, GCPtr pGC, xArc * parc)
  */
 
 void
-miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
+miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
 {
     int i;
     xArc *parc;
@@ -3396,3 +3396,12 @@ drawQuadrant(struct arc_def *def,
         y--;
     }
 }
+
+void
+miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
+{
+    if (pGC->lineWidth == 0)
+        miZeroPolyArc(pDraw, pGC, narcs, parcs);
+    else
+        miWideArc(pDraw, pGC, narcs, parcs);
+}
diff --git a/mi/mizerarc.c b/mi/mizerarc.c
index 9dac180..b216cf4 100644
--- a/mi/mizerarc.c
+++ b/mi/mizerarc.c
@@ -656,7 +656,7 @@ miZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
 
     for (arc = parcs, i = narcs; --i >= 0; arc++) {
         if (!miCanZeroArc(arc))
-            miPolyArc(pDraw, pGC, 1, arc);
+            miWideArc(pDraw, pGC, 1, arc);
         else {
             if (arc->width > arc->height)
                 n = arc->width + (arc->height >> 1);
commit bf1429b2034a577c994ff16b60d809d05ca99241
Author: Keith Packard <keithp at keithp.com>
Date:   Wed May 7 09:56:39 2014 -0700

    mi: Create miPolylines as a general-purpose line drawing function
    
    Instead of requiring all drivers to figure out which mi function to
    call for each of the four cases, create a single wrapper in mi that
    handles them correctly. Now drivers can simply use miPolylines in all
    cases.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/mi/mi.h b/mi/mi.h
index 1209a16..b8a4f05 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -452,6 +452,12 @@ extern _X_EXPORT void miWideDash(DrawablePtr /*pDrawable */ ,
                                  DDXPointPtr    /*pPts */
     );
 
+extern _X_EXPORT void miPolylines(DrawablePtr pDrawable,
+                                  GCPtr pGC,
+                                  int mode,
+                                  int npt,
+                                  DDXPointPtr pPts);
+
 /* miwindow.c */
 
 extern _X_EXPORT void miClearToBackground(WindowPtr /*pWin */ ,
diff --git a/mi/miwideline.c b/mi/miwideline.c
index b76e7a8..29ba12c 100644
--- a/mi/miwideline.c
+++ b/mi/miwideline.c
@@ -1979,3 +1979,23 @@ miWideDash(DrawablePtr pDrawable, GCPtr pGC,
     if (spanData)
         miCleanupSpanData(pDrawable, pGC, spanData);
 }
+
+void
+miPolylines(DrawablePtr drawable,
+            GCPtr gc,
+            int mode,
+            int n,
+            DDXPointPtr points)
+{
+    if (gc->lineWidth == 0) {
+        if (gc->lineStyle == LineSolid)
+            miZeroLine(drawable, gc, mode, n, points);
+        else
+            miZeroDashLine(drawable, gc, mode, n, points);
+    } else {
+        if (gc->lineStyle == LineSolid)
+            miWideLine(drawable, gc, mode, n, points);
+        else
+            miWideDash(drawable, gc, mode, n, points);
+    }
+}
commit 14d82a2bc3179160803c62c20746630d14e1b7d7
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 23:29:54 2014 -0700

    ephyr: Deal with non-root visual for window
    
    glx will sometimes select a non-root visual, deal with that by
    creating a suitable colormap and using that instead of attempting to
    use the default colormap.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 435919e..b156fb9 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -287,7 +287,8 @@ hostx_set_title(char *title)
 int
 hostx_init(void)
 {
-    uint32_t attr;
+    uint32_t attrs[2];
+    uint32_t attr_mask = 0;
     xcb_cursor_t empty_cursor;
     xcb_pixmap_t cursor_pxm;
     uint16_t red, green, blue;
@@ -299,7 +300,7 @@ hostx_init(void)
     const xcb_query_extension_reply_t *shm_rep;
     xcb_screen_t *xscreen;
 
-    attr =
+    attrs[0] =
         XCB_EVENT_MASK_BUTTON_PRESS
         | XCB_EVENT_MASK_BUTTON_RELEASE
         | XCB_EVENT_MASK_POINTER_MOTION
@@ -307,6 +308,7 @@ hostx_init(void)
         | XCB_EVENT_MASK_KEY_RELEASE
         | XCB_EVENT_MASK_EXPOSURE
         | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+    attr_mask |= XCB_CW_EVENT_MASK;
 
     EPHYR_DBG("mark");
 #ifdef GLAMOR
@@ -325,9 +327,18 @@ hostx_init(void)
     HostX.gc = xcb_generate_id(HostX.conn);
     HostX.depth = xscreen->root_depth;
 #ifdef GLAMOR
-    if (ephyr_glamor)
+    if (ephyr_glamor) {
         HostX.visual = ephyr_glamor_get_visual();
-    else
+        if (HostX.visual->visual_id != xscreen->root_visual) {
+            attrs[1] = xcb_generate_id(HostX.conn);
+            attr_mask |= XCB_CW_COLORMAP;
+            xcb_create_colormap(HostX.conn,
+                                XCB_COLORMAP_ALLOC_NONE,
+                                attrs[1],
+                                HostX.winroot,
+                                HostX.visual->visual_id);
+        }
+    } else
 #endif
         HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
 
@@ -379,9 +390,9 @@ hostx_init(void)
                               scrpriv->win_height,
                               0,
                               XCB_WINDOW_CLASS_COPY_FROM_PARENT,
-                              XCB_COPY_FROM_PARENT,
-                              XCB_CW_EVENT_MASK,
-                              &attr);
+                              HostX.visual->visual_id,
+                              attr_mask,
+                              attrs);
         }
         else {
             xcb_create_window(HostX.conn,
@@ -391,9 +402,9 @@ hostx_init(void)
                               0,0,100,100, /* will resize */
                               0,
                               XCB_WINDOW_CLASS_COPY_FROM_PARENT,
-                              XCB_COPY_FROM_PARENT,
-                              XCB_CW_EVENT_MASK,
-                              &attr);
+                              HostX.visual->visual_id,
+                              attr_mask,
+                              attrs);
 
             hostx_set_win_title(screen,
                                 "(ctrl+shift grabs mouse and keyboard)");
commit a11bbd875f3f90a3d02d727778cb1d3524cf59fd
Author: Eric Anholt <eric at anholt.net>
Date:   Fri May 30 10:39:30 2014 -0700

    glamor: Don't leak a prepare_access_gc() in putimage fallbacks.
    
    It turns out putimage doesn't use the GC tile or stipple anyway, so
    there's no need to do this.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_image.c b/glamor/glamor_image.c
index 4791d08..b38b412 100644
--- a/glamor/glamor_image.c
+++ b/glamor/glamor_image.c
@@ -88,8 +88,7 @@ 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))
+    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW))
         fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
     glamor_finish_access(drawable);
 }
commit 8da1e4e2bf28c3610cdbe1770a57be89578d37f5
Author: Markus Wick <markus at selfnet.de>
Date:   Wed May 14 23:08:18 2014 +0200

    glamor: Choose max fbo size by texture + viewport size
    
    The max size of renderbuffers and texture often match by accident, but
    as we always use textures, we should check for the right flag.  Also
    check for viewport size as this may be lower and we want to render to
    almost every pixmap.
    
    Signed-off-by: Markus Wick <markus at selfnet.de>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 08f6ba1..c398807 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -316,6 +316,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 {
     glamor_screen_private *glamor_priv;
     int gl_version;
+    int max_viewport_size;
 
 #ifdef RENDER
     PictureScreenPtr ps = GetPictureScreenIfSet(screen);
@@ -406,7 +407,9 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         epoxy_has_gl_extension("GL_ARB_map_buffer_range");
     glamor_priv->has_buffer_storage =
         epoxy_has_gl_extension("GL_ARB_buffer_storage");
-    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size);
+    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &max_viewport_size);
+    glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size);
 #ifdef MAX_FBO_SIZE
     glamor_priv->max_fbo_size = MAX_FBO_SIZE;
 #endif
commit 3778fab34bc00334edec4f845d0c6d43440f265a
Author: Markus Wick <markus at selfnet.de>
Date:   Wed May 14 23:08:17 2014 +0200

    glamor: Fix no-mipmap allocations
    
    With GL_TEXTURE_MIN_FILTER, we configure not to use mipmaps, but
    there's no real way until GL_ARB_texture_storage to dictate whether
    memory should be allocated for mipmap levels or not.
    
    GL_TEXTURE_MAX_LEVEL is a stronger hint to the driver than the
    filtering that we really don't want mipmap allocations.  Stops VARM
    wasting warnings from the nvidia driver.
    
    Signed-off-by: Markus Wick <markus at selfnet.de>
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c
index 5521683..090dfd8 100644
--- a/glamor/glamor_fbo.c
+++ b/glamor/glamor_fbo.c
@@ -347,6 +347,7 @@ _glamor_create_tex(glamor_screen_private *glamor_priv,
         glamor_make_current(glamor_priv);
         glGenTextures(1, &tex);
         glBindTexture(GL_TEXTURE_2D, tex);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
         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,
diff --git a/glamor/glamor_font.c b/glamor/glamor_font.c
index f747d59..57c607d 100644
--- a/glamor/glamor_font.c
+++ b/glamor/glamor_font.c
@@ -95,6 +95,7 @@ glamor_font_get(ScreenPtr screen, FontPtr font)
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, glamor_font->texture_id);
 
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 54b414b..789d377 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -717,6 +717,7 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
     }
 
     glBindTexture(GL_TEXTURE_2D, *tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
commit 1095c262502332bc570a9b288b01da51c1fa10ec
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Fri Jun 6 17:54:22 2014 -0700

    config: show default path in help for --with-xkb-bin-directory
    
    Now shows:
      --with-xkb-bin-directory=DIR
                              Directory containing xkbcomp program (default:
                              ${bindir})
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 0a6e772..dabebb9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1424,7 +1424,7 @@ AC_DEFINE(SHAPE, 1, [Support SHAPE extension])
 
 AC_DEFINE_DIR(XKB_BASE_DIRECTORY, XKBPATH, [Path to XKB data])
 AC_ARG_WITH(xkb-bin-directory,
-				AS_HELP_STRING([--with-xkb-bin-directory=DIR], [Directory containing xkbcomp program]),
+				AS_HELP_STRING([--with-xkb-bin-directory=DIR], [Directory containing xkbcomp program (default: ${bindir})]),
 				[XKB_BIN_DIRECTORY="$withval"],
 				[XKB_BIN_DIRECTORY="$bindir"])
 


More information about the Xquartz-changes mailing list