xserver: Branch 'master' - 34 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Mar 17 17:30:52 PDT 2014


 glamor/glamor.c                    |   37 +++++
 glamor/glamor.h                    |   19 --
 glamor/glamor_addtraps.c           |    2 
 glamor/glamor_copyarea.c           |   19 +-
 glamor/glamor_copyplane.c          |   15 +-
 glamor/glamor_core.c               |   65 +++++++--
 glamor/glamor_egl.c                |  129 +++++++------------
 glamor/glamor_fbo.c                |    2 
 glamor/glamor_fill.c               |   74 ++++++----
 glamor/glamor_fillspans.c          |   11 -
 glamor/glamor_getimage.c           |    2 
 glamor/glamor_getspans.c           |    2 
 glamor/glamor_glx.c                |    8 -
 glamor/glamor_glyphblt.c           |  251 +++++++++++++++++++++++++++++++++++++
 glamor/glamor_glyphs.c             |   21 ++-
 glamor/glamor_gradient.c           |   14 --
 glamor/glamor_picture.c            |    4 
 glamor/glamor_pixmap.c             |   20 --
 glamor/glamor_polyfillrect.c       |   11 -
 glamor/glamor_polylines.c          |   28 ++--
 glamor/glamor_priv.h               |   56 +++++---
 glamor/glamor_putimage.c           |  197 -----------------------------
 glamor/glamor_render.c             |   38 ++---
 glamor/glamor_setspans.c           |   12 +
 glamor/glamor_tile.c               |    4 
 glamor/glamor_trapezoid.c          |    6 
 glamor/glamor_triangles.c          |   15 --
 glamor/glamor_utils.h              |   33 ++--
 glamor/glamor_xv.c                 |    3 
 hw/kdrive/ephyr/ephyr_glamor_glx.c |   16 ++
 hw/kdrive/ephyr/ephyr_glamor_glx.h |   10 +
 hw/kdrive/ephyr/hostx.c            |    7 -
 miext/sync/misyncstr.h             |    1 
 33 files changed, 616 insertions(+), 516 deletions(-)

New commits:
commit d18d3f6d18aa7827748f7ba14efd405b525883d0
Merge: 81a4952 6649d00
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 17:29:56 2014 -0700

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


More information about the xorg-commit mailing list