xserver: Branch 'master' - 38 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Jul 17 20:07:22 PDT 2014


 config/config.c                            |  161 ------
 config/udev.c                              |   10 
 glamor/Makefile.am                         |   15 
 glamor/glamor.c                            |   49 +-
 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_fill.c                       |  356 --------------
 glamor/glamor_glyphblt.c                   |  154 ++----
 glamor/glamor_glyphs.c                     |   10 
 glamor/glamor_gradient.c                   |   19 
 glamor/glamor_largepixmap.c                |   13 
 glamor/glamor_lines.c                      |  187 +++++++
 glamor/glamor_picture.c                    |   18 
 glamor/glamor_pixmap.c                     |  509 ---------------------
 glamor/glamor_points.c                     |    3 
 glamor/glamor_polylines.c                  |  136 -----
 glamor/glamor_prepare.c                    |  274 +++++++++++
 glamor/glamor_prepare.h                    |   52 ++
 glamor/glamor_priv.h                       |  251 +++++-----
 glamor/glamor_program.c                    |   56 +-
 glamor/glamor_program.h                    |    6 
 glamor/glamor_render.c                     |   89 ---
 glamor/glamor_segment.c                    |   44 -
 glamor/glamor_segs.c                       |  188 +++++++
 glamor/glamor_spans.c                      |    3 
 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_xv.c                         |  265 +++--------
 hw/kdrive/ephyr/Makefile.am                |    5 
 hw/kdrive/ephyr/ephyr.c                    |    4 
 hw/kdrive/ephyr/ephyr.h                    |   10 
 hw/kdrive/ephyr/ephyr_glamor_glx.c         |   24 -
 hw/kdrive/ephyr/ephyr_glamor_xv.c          |  161 ++++++
 hw/kdrive/ephyr/ephyrinit.c                |   12 
 hw/kdrive/ephyr/ephyrvideo.c               |   34 -
 hw/kdrive/ephyr/hostx.c                    |   34 -
 hw/kdrive/src/kxv.c                        |   81 ---
 hw/kdrive/src/kxv.h                        |   23 
 hw/xfree86/common/xf86platformBus.c        |   58 --
 hw/xfree86/common/xf86platformBus.h        |   98 +++-
 hw/xfree86/common/xf86xv.c                 |   53 --
 hw/xfree86/common/xf86xv.h                 |   36 -
 hw/xfree86/glamor_egl/Makefile.am          |    3 
 hw/xfree86/glamor_egl/glamor_xf86_xv.c     |  185 +++++++
 hw/xfree86/os-support/linux/lnx_platform.c |   52 --
 include/hotplug.h                          |   69 --
 mi/mi.h                                    |   11 
 mi/miarc.c                                 |   11 
 mi/mifillarc.c                             |  146 ++----
 mi/miwideline.c                            |   20 
 mi/mizerarc.c                              |    2 
 mi/mizerline.c                             |   16 
 62 files changed, 3232 insertions(+), 3567 deletions(-)

New commits:
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 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)");


More information about the xorg-commit mailing list