=== modified file 'NEWS'
--- NEWS	2011-07-21 09:50:35 +0000
+++ NEWS	2011-08-18 07:56:25 +0000
@@ -1,3 +1,8 @@
+glcompbench 2011.08 (20110818)
+==============================
+
+* Add xrender based compositing test.
+
 glcompbench 2011.07 (20110719)
 ==============================
 

=== modified file 'doc/gl-composite-benchmark.1.in'
--- doc/gl-composite-benchmark.1.in	2011-06-24 14:56:59 +0000
+++ doc/gl-composite-benchmark.1.in	2011-08-18 07:56:25 +0000
@@ -1,4 +1,4 @@
-.TH GL-COMPOSITE-BENCHMARK "1" "June 2011" "gl-composite-benchmark @appversion@"
+.TH GL-COMPOSITE-BENCHMARK "1" "August 2011" "gl-composite-benchmark @appversion@"
 .SH NAME
 .SH SYNOPSIS
 .B gl-composite-benchmark [OPTIONS] [-- [GLCOMPBENCH_OPTIONS]]

=== modified file 'doc/glcompbench.1.in'
--- doc/glcompbench.1.in	2011-06-24 14:56:59 +0000
+++ doc/glcompbench.1.in	2011-08-18 07:56:25 +0000
@@ -1,4 +1,4 @@
-.TH @APPNAME@ "1" "June 2011" "@appname@ @appversion@"
+.TH @APPNAME@ "1" "August 2011" "@appname@ @appversion@"
 .SH NAME
 @appname@ \- OpenGL (ES) 2.0 compositing benchmark
 .SH SYNOPSIS

=== added file 'src/composite-canvas-xrender.cc'
--- src/composite-canvas-xrender.cc	1970-01-01 00:00:00 +0000
+++ src/composite-canvas-xrender.cc	2011-08-17 14:15:49 +0000
@@ -0,0 +1,246 @@
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#include <string>
+#include <sstream>
+#include <cstdlib>
+
+#include "composite-canvas-xrender.h"
+#include "composite-window-xrender.h"
+#include "options.h"
+#include "log.h"
+
+CompositeCanvasXRender::~CompositeCanvasXRender()
+{
+    release_resources();
+}
+
+bool
+CompositeCanvasXRender::have_xrender()
+{
+    int ignore, major, minor;
+    bool have_xrender = false;
+        
+    /* Check for the XShm extension */
+    if (XQueryExtension(xdpy_, "RENDER", &ignore, &ignore, &ignore)) {
+        if (XRenderQueryVersion(xdpy_, &major, &minor)) {
+            Log::debug("XRender extension version %d.%d\n",
+                       major, minor);
+            have_xrender = true;
+        }
+    }
+
+    return have_xrender;
+}
+
+bool
+CompositeCanvasXRender::have_xdbe()
+{
+    int major, minor;
+    bool have_xdbe = false;
+        
+    /* Check for the Xdbe extension */
+    if (XdbeQueryExtension(xdpy_, &major, &minor)) {
+        Log::debug("Xdbe extension version %d.%d\n", major, minor);
+        have_xdbe = true;
+    }
+    else {
+        Log::info("** Xdbe extension not supported. You may experience flickering.\n");
+    }
+
+    return have_xdbe;
+}
+
+bool
+CompositeCanvasXRender::ensure_xdbe_back_buffer()
+{
+    XdbeScreenVisualInfo *xdbe_screen_vis_info;
+    XWindowAttributes canvas_attr;
+    int num_screens = 1;
+    bool dbe_visual_found = false;
+
+    if (xdbe_back_buffer_)
+        return true;
+
+    if (!have_xdbe())
+        return false;
+
+    /* Check if the canvas visual supports double-buffering */
+    if (!XGetWindowAttributes(xdpy_, canvas_, &canvas_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    xdbe_screen_vis_info = XdbeGetVisualInfo(xdpy_, &canvas_, &num_screens);
+    if (!xdbe_screen_vis_info || num_screens == 0) {
+        Log::error("XdbeGetVisualInfo failed!\n");
+        return false;
+    }
+
+    for (int i = 0; i < xdbe_screen_vis_info[0].count; i++) {
+        XdbeVisualInfo *vis_info = &xdbe_screen_vis_info[0].visinfo[i];
+        if (vis_info->visual == XVisualIDFromVisual(canvas_attr.visual)) {
+            dbe_visual_found = true;
+            break;
+        }
+    }
+
+    XdbeFreeVisualInfo(xdbe_screen_vis_info);
+ 
+    if (!dbe_visual_found) {
+        Log::info("** The window visual does not support double buffering."
+                  " You may experience flickering!\n");
+        return false;
+    }
+
+    /* Allocate the back buffer */
+    xdbe_back_buffer_ = XdbeAllocateBackBufferName(xdpy_, canvas_,
+                                                   XdbeBackground);
+    if (!xdbe_back_buffer_) {
+        Log::error("XdbeAllocateBufferName failed!\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool
+CompositeCanvasXRender::ensure_xrender_picture()
+{
+    Drawable drawable;
+
+    if (xrender_picture_)
+        return true;
+
+    if (!have_xrender())
+        return false;
+
+    if (!ensure_xdbe_back_buffer())
+        drawable = canvas_;
+    else
+        drawable = xdbe_back_buffer_;
+
+    XWindowAttributes canvas_attr;
+
+    if (!XGetWindowAttributes(xdpy_, canvas_, &canvas_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    /* TODO: should we free this when we are done? */
+    XRenderPictFormat *pict_format;
+        
+    pict_format = XRenderFindVisualFormat(xdpy_, canvas_attr.visual);
+    if (!pict_format) {
+        Log::error("XRenderFindVisualFormat failed!\n");
+        release_resources();
+        return false;
+    }
+
+    xrender_picture_ = XRenderCreatePicture(xdpy_, drawable, pict_format,
+                                            0, NULL);
+    if (!xrender_picture_) {
+        Log::error("XRenderCreatePicture failed!\n");
+        release_resources();
+        return false;
+    }
+
+    return true;
+}
+
+XVisualInfo *
+CompositeCanvasXRender::get_canvas_xvisualinfo()
+{
+    int num_visuals;
+    XVisualInfo vis_tmpl;
+    XVisualInfo *vis_info;
+
+    vis_tmpl.depth = 32;
+    vis_tmpl.bits_per_rgb = 8;
+    vis_info = XGetVisualInfo(xdpy_, VisualDepthMask | VisualBitsPerRGBMask,
+                              &vis_tmpl, &num_visuals);
+    if (!vis_info) {
+        Log::error("Error: couldn't get X visual\n");
+        return 0;
+    }
+
+    return vis_info;
+}
+
+void
+CompositeCanvasXRender::reshape(int width, int height)
+{
+    CompositeCanvas::reshape(width, height);
+
+    release_resources();
+    ensure_xrender_picture();
+}
+
+bool
+CompositeCanvasXRender::make_current()
+{
+    return ensure_xrender_picture();
+}
+
+void
+CompositeCanvasXRender::release_resources()
+{
+    if (xrender_picture_)
+        XRenderFreePicture(xdpy_, xrender_picture_);
+
+    if (xdbe_back_buffer_)
+        XdbeDeallocateBackBufferName(xdpy_, xdbe_back_buffer_);
+
+    xrender_picture_ = 0;
+    xdbe_back_buffer_ = 0;
+}
+
+CompositeWindow *
+CompositeCanvasXRender::create_window(Window win)
+{
+    return new CompositeWindowXRender(xdpy_, win);
+}
+
+void
+CompositeCanvasXRender::update_screen()
+{
+    if (xdbe_back_buffer_) {
+        XdbeSwapInfo swap_info = {canvas_, XdbeBackground};
+        XdbeSwapBuffers(xdpy_, &swap_info, 1);
+    }
+}
+
+std::string
+CompositeCanvasXRender::info_string()
+{
+    std::stringstream ss;
+    int major, minor;
+
+    ss << "    XRender ";
+    if (XRenderQueryVersion(xdpy_, &major, &minor))
+        ss << major << "." << minor << std::endl;
+    else
+        ss << "(Not Available)" << std::endl;
+
+    return ss.str();
+}

=== added file 'src/composite-canvas-xrender.h'
--- src/composite-canvas-xrender.h	1970-01-01 00:00:00 +0000
+++ src/composite-canvas-xrender.h	2011-08-17 14:15:49 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#ifndef COMPOSITE_CANVAS_XRENDER_H_
+#define COMPOSITE_CANVAS_XRENDER_H_
+
+#include "composite-canvas.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/Xdbe.h>
+
+class CompositeCanvasXRender: public CompositeCanvas
+{
+public:
+    CompositeCanvasXRender() :
+        CompositeCanvas("xrender"), xrender_picture_(0), xdbe_back_buffer_(0)
+        {}
+
+    virtual ~CompositeCanvasXRender();
+
+    std::string info_string();
+    Picture xrender_picture() { return xrender_picture_; }
+
+protected:
+    XVisualInfo *get_canvas_xvisualinfo();
+    bool make_current();
+    void release_resources();
+    CompositeWindow *create_window(Window win);
+    void update_screen();
+    void reshape(int width, int height);
+
+private:
+    bool have_xdbe();
+    bool have_xrender();
+    bool ensure_xdbe_back_buffer();
+    bool ensure_xrender_picture();
+
+    Picture xrender_picture_;
+    XdbeBackBuffer xdbe_back_buffer_;
+};
+
+#endif /* COMPOSITE_CANVAS_XRENDER_H_ */

=== modified file 'src/composite-canvas.cc'
--- src/composite-canvas.cc	2011-07-18 13:28:08 +0000
+++ src/composite-canvas.cc	2011-08-03 14:34:10 +0000
@@ -448,7 +448,7 @@
     {
         CompositeWindow *comp_win = *iter;
         if (comp_win->get_texture().is_valid())
-            comp_win->update_texture_from_pixmap(false);
+            comp_win->update_texture_from_pixmap();
     }
 }
 

=== modified file 'src/composite-canvas.h'
--- src/composite-canvas.h	2011-07-18 13:28:08 +0000
+++ src/composite-canvas.h	2011-08-03 17:00:15 +0000
@@ -52,6 +52,9 @@
     virtual std::string info_string() { return std::string(); }
     
     const std::string &type() { return type_; }
+    Display *xdisplay() { return xdpy_; }
+    unsigned int width() { return width_; }
+    unsigned int height() { return height_; }
 
 protected:
     virtual XVisualInfo *get_canvas_xvisualinfo() = 0;

=== added file 'src/composite-test-xrender.cc'
--- src/composite-test-xrender.cc	1970-01-01 00:00:00 +0000
+++ src/composite-test-xrender.cc	2011-08-03 17:14:34 +0000
@@ -0,0 +1,124 @@
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#include <X11/extensions/Xrender.h>
+#include <cmath>
+
+#include "composite-test.h"
+#include "composite-canvas-xrender.h"
+
+CompositeTestXRender::CompositeTestXRender() :
+    CompositeTest("xrender", "xrender")
+{
+    options_["filter"] = CompositeTest::Option("filter", "bilinear",
+                                               "Filter to use [nearest, bilinear]");
+}
+
+void
+CompositeTestXRender::init()
+{
+    XRenderColor half_transparent = {0x7fff, 0x7fff, 0x7fff, 0x7fff};
+    half_transparent_mask_ = XRenderCreateSolidFill(canvas_->xdisplay(),
+                                                    &half_transparent);
+}
+
+void
+CompositeTestXRender::deinit()
+{
+    if (half_transparent_mask_) {
+        XRenderFreePicture(canvas_->xdisplay(), half_transparent_mask_);
+        half_transparent_mask_ = 0;
+    }
+}
+
+void
+CompositeTestXRender::prepare_for_run()
+{
+    if (options_["filter"].value == "bilinear")
+        xrender_filter_ = FilterBilinear;
+    else
+        xrender_filter_ = FilterNearest;
+}
+
+void
+CompositeTestXRender::draw(std::list<CompositeWindow *> &window_list)
+{
+    CompositeCanvasXRender *canvas_xrender =
+        static_cast<CompositeCanvasXRender *>(canvas_);
+    Display *xdpy = canvas_->xdisplay();
+
+    Picture dest_picture = canvas_xrender->xrender_picture();
+    int dest_width = canvas_->width();
+    int dest_height = canvas_->height();
+
+    /* Clear the screen with color matching GL {0.1, 0.1, 0.3, 1.0} */
+    XRenderColor clear = {6554, 6554, 19661, 65535};
+
+    XRenderFillRectangle(xdpy, PictOpSrc, dest_picture, &clear,
+                         0, 0, dest_width, dest_height);
+
+    /* Find out how many windows are visible and calculate the angular step */
+    int visible_windows(num_visible_windows(window_list));
+    float angular_step(2 * M_PI / visible_windows);
+
+    /* Draw the windows in a circle using the calculated angular step */
+    int i(0);
+    for(std::list<CompositeWindow*>::iterator iter = window_list.begin();
+        iter != window_list.end(); ++iter)
+    {
+        CompositeWindow *comp_win = *iter;
+        Picture xrender_picture = static_cast<Picture>(comp_win->get_texture().i);
+        if (xrender_picture) {
+            int width = comp_win->width();
+            int height = comp_win->height();
+
+            /* Calculate the new position of the composited window center */
+            int x0 = dest_width / 2 + cos(i * angular_step) * dest_width / 4;
+            int y0 = dest_height / 2 + sin(i * angular_step) * dest_height / 4;
+
+            /* Calculate the new position of the upper left corner */
+            x0 -= dest_width / 4;
+            y0 -= dest_height / 4;
+
+            /* Scale the window to fit in dest_width/2 and dest_height/2 */
+            XTransform xform = {{{0}}};
+            xform.matrix[0][0] = XDoubleToFixed(2.0 * width / dest_width);
+            xform.matrix[1][1] = XDoubleToFixed(2.0 * height / dest_height);
+            xform.matrix[2][2] = XDoubleToFixed(1.0);
+
+            XRenderSetPictureFilter(xdpy, xrender_picture,
+                                    xrender_filter_, NULL, 0);
+            XRenderSetPictureTransform(xdpy, xrender_picture, &xform);
+
+            /* Draw the window Picture to the canvas Picture */
+            XRenderComposite(xdpy, PictOpOver, xrender_picture,
+                             half_transparent_mask_, dest_picture,
+                             0, 0, 0, 0, x0, y0,
+                             dest_width / 2, dest_height / 2);
+
+            i++;
+        }
+    }
+}
+
+

=== modified file 'src/composite-test.h'
--- src/composite-test.h	2011-07-19 08:29:50 +0000
+++ src/composite-test.h	2011-08-03 17:14:34 +0000
@@ -28,6 +28,7 @@
 #include <list>
 #include <map>
 #include <pixman.h>
+#include <X11/extensions/Xrender.h>
 
 #include "stack.h"
 #include "program.h"
@@ -192,4 +193,20 @@
     pixman_filter_t pixman_filter_;
 };
 
+class CompositeTestXRender : public CompositeTest
+{
+public:
+    CompositeTestXRender();
+
+    virtual void init();
+    virtual void deinit();
+    virtual void prepare_for_run();
+    virtual void draw(std::list<CompositeWindow*> &window_list);
+
+private:
+    Picture half_transparent_mask_;
+    const char *xrender_filter_;
+    
+};
+
 #endif // COMPOSITE_TEST_H_

=== modified file 'src/composite-window-eglimage.cc'
--- src/composite-window-eglimage.cc	2011-04-04 12:56:06 +0000
+++ src/composite-window-eglimage.cc	2011-08-03 14:34:10 +0000
@@ -37,34 +37,44 @@
 
 CompositeWindowEGLImage::~CompositeWindowEGLImage()
 {
-    if (egl_image_)
+    release_tfp();
+}
+
+void
+CompositeWindowEGLImage::release_tfp()
+{
+    if (egl_image_) {
         eglDestroyImageKHR_(egl_display_, egl_image_);
+        egl_image_ = 0;
+    }
 }
 
 void
-CompositeWindowEGLImage::update_texture_from_pixmap(bool recreate)
+CompositeWindowEGLImage::update_texture()
 {
+    CompositeWindowGL::update_texture();
+
     const EGLint egl_image_attribs[] = {
         EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
         EGL_NONE
     };
 
+    release_tfp();
+
+    egl_image_ = eglCreateImageKHR_(egl_display_, EGL_NO_CONTEXT,
+                                    EGL_NATIVE_PIXMAP_KHR,
+                                    reinterpret_cast<EGLClientBuffer>(pix_),
+                                    egl_image_attribs);
+
+    Log::debug("    => EGLImage <= %p\n", egl_image_);
+    Log::debug("    => eglError 0x%x\n", eglGetError());
+}
+
+void
+CompositeWindowEGLImage::update_texture_from_pixmap()
+{
     Profiler::ScopedSamples scoped_tfp(CompositeWindow::get_profiler_tfp_pair());
 
-    if (recreate) {
-        if (egl_image_) {
-            eglDestroyImageKHR_(egl_display_, egl_image_);
-            egl_image_ = 0;
-        }
-        egl_image_ = eglCreateImageKHR_(egl_display_, EGL_NO_CONTEXT,
-                                        EGL_NATIVE_PIXMAP_KHR,
-                                        reinterpret_cast<EGLClientBuffer>(pix_),
-                                        egl_image_attribs);
-
-        Log::debug("    => EGLImage <= %p\n", egl_image_);
-        Log::debug("    => eglError 0x%x\n", eglGetError());
-    }
-
     /* Update texture with new data */
     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
 

=== modified file 'src/composite-window-eglimage.h'
--- src/composite-window-eglimage.h	2011-07-15 08:16:54 +0000
+++ src/composite-window-eglimage.h	2011-08-03 14:34:10 +0000
@@ -39,9 +39,11 @@
         egl_image_(0), egl_display_(egl_display) {}
     ~CompositeWindowEGLImage();
 
-    void update_texture_from_pixmap(bool recreate);
+    void update_texture();
+    void update_texture_from_pixmap();
 
 private:
+    void release_tfp();
     EGLImageKHR egl_image_;
     EGLDisplay egl_display_;
 };

=== modified file 'src/composite-window-gl.cc'
--- src/composite-window-gl.cc	2011-07-15 08:16:54 +0000
+++ src/composite-window-gl.cc	2011-08-03 14:34:10 +0000
@@ -30,11 +30,9 @@
         glDeleteTextures(1, &tex_);
 }
 
-bool
+void
 CompositeWindowGL::update_texture()
 {
-    bool ret = false;
-
     if (!tex_ && attr_.map_state != 0) {
         glGenTextures(1, &tex_);
 
@@ -45,14 +43,10 @@
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
         Log::debug("    => texture <= 0x%x\n", (unsigned) tex_);
-        ret = true;
     }
     else if (tex_ && attr_.map_state == 0) {
         Log::debug("    => Deleting texture 0x%x\n", (unsigned) tex_);
         glDeleteTextures(1, &tex_);
-        tex_ = 0;
     }
-
-    return ret;
 }
 

=== modified file 'src/composite-window-gl.h'
--- src/composite-window-gl.h	2011-07-15 08:16:54 +0000
+++ src/composite-window-gl.h	2011-08-03 14:34:10 +0000
@@ -36,7 +36,7 @@
     virtual ~CompositeWindowGL();
 
     virtual Texture get_texture() { return CompositeWindow::Texture(tex_); }
-    virtual bool update_texture();
+    virtual void update_texture();
 
 protected:
     GLuint tex_;

=== modified file 'src/composite-window-glxpixmap.cc'
--- src/composite-window-glxpixmap.cc	2011-07-20 09:17:11 +0000
+++ src/composite-window-glxpixmap.cc	2011-08-03 14:34:10 +0000
@@ -52,24 +52,28 @@
 }
 
 void
-CompositeWindowGLXPixmap::update_texture_from_pixmap(bool recreate)
+CompositeWindowGLXPixmap::update_texture()
 {
+    CompositeWindowGL::update_texture();
+
     const int pixmap_attribs[] = {
         GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
         GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
         None
     };
 
+    release_tfp();
+    glx_pixmap_ = glXCreatePixmap(xdpy_, glx_fbconfig_, pix_,
+                                  pixmap_attribs);
+
+    Log::debug("    => GLXPixmap <= %p\n", glx_pixmap_);
+}
+
+void
+CompositeWindowGLXPixmap::update_texture_from_pixmap()
+{
     Profiler::ScopedSamples scoped_tfp(CompositeWindow::get_profiler_tfp_pair());
 
-    if (recreate) {
-        release_tfp();
-        glx_pixmap_ = glXCreatePixmap(xdpy_, glx_fbconfig_, pix_,
-                                      pixmap_attribs);
-
-        Log::debug("    => GLXPixmap <= %p\n", glx_pixmap_);
-    }
-
     /* Update texture with new data */
     glXWaitX();
 

=== modified file 'src/composite-window-glxpixmap.h'
--- src/composite-window-glxpixmap.h	2011-07-20 08:23:33 +0000
+++ src/composite-window-glxpixmap.h	2011-08-03 14:34:10 +0000
@@ -37,7 +37,8 @@
         glx_fbconfig_ (glx_fbconfig), glx_pixmap_bound_(false) {}
     ~CompositeWindowGLXPixmap();
 
-    void update_texture_from_pixmap(bool recreate);
+    void update_texture();
+    void update_texture_from_pixmap();
 
 private:
     void release_tfp();

=== modified file 'src/composite-window-pixman.cc'
--- src/composite-window-pixman.cc	2011-07-19 16:01:23 +0000
+++ src/composite-window-pixman.cc	2011-08-03 14:34:10 +0000
@@ -188,31 +188,31 @@
 }
 
 void
-CompositeWindowPixman::update_texture_from_pixmap(bool recreate)
+CompositeWindowPixman::update_texture()
+{
+    release_resources();
+
+    if (use_shm_) {
+        if (!ensure_ximage_shm() || !ensure_pixman_image())
+            return;
+    }
+    else {
+        if (!ensure_ximage() || !ensure_pixman_image())
+            return;
+    }
+}
+
+void
+CompositeWindowPixman::update_texture_from_pixmap()
 {
     Profiler::ScopedSamples scoped_tfp(CompositeWindow::get_profiler_tfp_pair());
 
-    if (recreate)
-        release_resources();
-
     if (use_shm_) {
-        if (!ensure_ximage_shm() || !ensure_pixman_image())
-            return;
-
         XShmGetImage(xdpy_, pix_, ximage_, 0, 0, AllPlanes);
     }
     else {
-        if (!ensure_ximage() || !ensure_pixman_image())
-            return;
-
         XGetSubImage(xdpy_, pix_, 0, 0, width_, height_, AllPlanes, ZPixmap,
                      ximage_, 0, 0);
     }
 
 }
-
-bool
-CompositeWindowPixman::update_texture()
-{
-    return false;
-}

=== modified file 'src/composite-window-pixman.h'
--- src/composite-window-pixman.h	2011-07-18 16:26:56 +0000
+++ src/composite-window-pixman.h	2011-08-03 14:34:10 +0000
@@ -47,8 +47,8 @@
         return CompositeWindow::Texture(pixman_image_);
     }
 
-    bool update_texture();
-    void update_texture_from_pixmap(bool recreate);
+    void update_texture();
+    void update_texture_from_pixmap();
 
 private:
     bool have_xshm();

=== modified file 'src/composite-window-ximage.cc'
--- src/composite-window-ximage.cc	2011-04-04 12:56:06 +0000
+++ src/composite-window-ximage.cc	2011-08-03 14:34:10 +0000
@@ -36,23 +36,27 @@
 }
 
 void
-CompositeWindowXImage::update_texture_from_pixmap(bool recreate)
+CompositeWindowXImage::update_texture()
+{
+    CompositeWindowGL::update_texture();
+
+    glBindTexture(GL_TEXTURE_2D, tex_);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+                 width_, height_, 0,
+                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+}
+
+void
+CompositeWindowXImage::update_texture_from_pixmap()
 {
     Profiler::ScopedSamples scoped_tfp(CompositeWindow::get_profiler_tfp_pair());
 
-    glBindTexture(GL_TEXTURE_2D, tex_);
-
-    if (recreate) {
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-                width_, height_, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-    }
-
     if (ximage_)
         XDestroyImage(ximage_);
 
     ximage_ = XGetImage(xdpy_, pix_, 0, 0, width_, height_, AllPlanes, ZPixmap);
     if (ximage_) {
+        glBindTexture(GL_TEXTURE_2D, tex_);
         /*
          * Note that the data we get from the pixmap is BGRA but the texture
          * expects RGBA, so what we are doing here is technically incorrect

=== modified file 'src/composite-window-ximage.h'
--- src/composite-window-ximage.h	2011-07-15 08:16:54 +0000
+++ src/composite-window-ximage.h	2011-08-03 14:34:10 +0000
@@ -35,7 +35,8 @@
         CompositeWindowGL(xdpy, win), ximage_(0) {}
     ~CompositeWindowXImage();
 
-    void update_texture_from_pixmap(bool recreate);
+    void update_texture();
+    void update_texture_from_pixmap();
 
 private:
     XImage *ximage_;

=== added file 'src/composite-window-xrender.cc'
--- src/composite-window-xrender.cc	1970-01-01 00:00:00 +0000
+++ src/composite-window-xrender.cc	2011-08-03 17:05:08 +0000
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xrender.h>
+
+#include "composite-window-xrender.h"
+#include "log.h"
+
+CompositeWindowXRender::~CompositeWindowXRender()
+{
+    release_resources();
+}
+
+void
+CompositeWindowXRender::release_resources()
+{
+    if (xrender_picture_)
+        XRenderFreePicture(xdpy_, xrender_picture_);
+
+    xrender_picture_ = 0;
+}
+
+bool
+CompositeWindowXRender::ensure_xrender_picture()
+{
+    if (xrender_picture_)
+        return true;
+
+    XWindowAttributes win_attr;
+
+    if (!XGetWindowAttributes(xdpy_, win_, &win_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    /* TODO: should we free this when we are done? */
+    XRenderPictFormat *pict_format;
+        
+    pict_format = XRenderFindVisualFormat(xdpy_, win_attr.visual);
+    if (!pict_format) {
+        Log::error("XRenderFindVisualFormat failed!\n");
+        release_resources();
+        return false;
+    }
+
+    xrender_picture_ = XRenderCreatePicture(xdpy_, win_, pict_format,
+                                            0, NULL);
+    if (!xrender_picture_) {
+        Log::error("XRenderCreatePicture failed!\n");
+        release_resources();
+        return false;
+    }
+
+    return true;
+}
+
+void
+CompositeWindowXRender::update_texture()
+{
+    release_resources();
+    ensure_xrender_picture();
+}
+
+void
+CompositeWindowXRender::update_texture_from_pixmap()
+{
+    Profiler::ScopedSamples scoped_tfp(CompositeWindow::get_profiler_tfp_pair());
+}
+

=== added file 'src/composite-window-xrender.h'
--- src/composite-window-xrender.h	1970-01-01 00:00:00 +0000
+++ src/composite-window-xrender.h	2011-08-03 17:05:08 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2011 Linaro Limited
+ *
+ * This file is part of glcompbench.
+ *
+ * glcompbench is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * glcompbench is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with glcompbench.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ *  Jesse Barker <jesse.barker@linaro.org>
+ */
+
+#ifndef COMPOSITE_WINDOW_PIXMAN_H_
+#define COMPOSITE_WINDOW_PIXMAN_H_
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrender.h>
+
+#include "composite-window.h"
+#include "options.h"
+
+class CompositeWindowXRender : public CompositeWindow
+{
+public:
+    CompositeWindowXRender(Display *xdpy, Window win) :
+        CompositeWindow(xdpy, win), xrender_picture_(0) {}
+
+    ~CompositeWindowXRender();
+
+    CompositeWindow::Texture get_texture()
+    {
+        return CompositeWindow::Texture(xrender_picture_);
+    }
+
+    void update_texture();
+    void update_texture_from_pixmap();
+
+private:
+    bool ensure_xrender_picture();
+    void release_resources();
+
+    Picture xrender_picture_;
+};
+
+#endif

=== modified file 'src/composite-window.cc'
--- src/composite-window.cc	2011-07-15 08:16:54 +0000
+++ src/composite-window.cc	2011-08-03 14:34:10 +0000
@@ -96,10 +96,10 @@
     }
 
     /* Create or delete texture if needed */
-    update_tfp = update_texture() || update_tfp;
-
-    if (update_tfp)
-        update_texture_from_pixmap(true);
+    if (update_tfp) {
+        update_texture();
+        update_texture_from_pixmap();
+    }
 
     /*
      * We have to free the pixmap after calling update_texture_from_pixmap(),
@@ -123,5 +123,5 @@
     if (damage_)
         XDamageSubtract(xdpy_, damage_, None, None);
 
-    update_texture_from_pixmap(false);
+    update_texture_from_pixmap();
 }

=== modified file 'src/composite-window.h'
--- src/composite-window.h	2011-07-15 08:16:54 +0000
+++ src/composite-window.h	2011-08-03 17:02:08 +0000
@@ -37,20 +37,27 @@
 
     union Texture {
         Texture(void *p): p(p) {}
-        Texture(unsigned int i): i(i) {}
+        Texture(long unsigned int i): i(i) {}
         bool is_valid() { return p != 0 && i != 0; }
         void *p;
-        unsigned int i;
+        long unsigned int i;
     };
 
     virtual ~CompositeWindow();
     void update();
     void handle_damage();
     Window get_xwindow();
+    unsigned int width() { return width_; }
+    unsigned int height() { return height_; }
 
     virtual Texture get_texture() = 0;
-    virtual bool update_texture() = 0;
-    virtual void update_texture_from_pixmap(bool recreate) = 0;
+    /* 
+     * Update the texture itself (whatever that happens
+     * to be, eg GL texture + TFP, pixman image)
+     */
+    virtual void update_texture() = 0;
+    /* Update the texture contents from the pixmap */
+    virtual void update_texture_from_pixmap() = 0;
 
 protected:
     Display *xdpy_;

=== modified file 'src/glcompbench.cc'
--- src/glcompbench.cc	2011-07-19 08:18:28 +0000
+++ src/glcompbench.cc	2011-08-04 10:49:59 +0000
@@ -29,6 +29,7 @@
 #include "composite-canvas-glx.h"
 #endif
 #include "composite-canvas-pixman.h"
+#include "composite-canvas-xrender.h"
 
 #include "composite-test.h"
 #include "benchmark.h"
@@ -39,6 +40,7 @@
     "default",
     "brick",
     "pixman",
+    "xrender",
     NULL
 };
 
@@ -135,6 +137,7 @@
 {
     std::list<CompositeCanvas *> canvas_list;
     canvas_list.push_back(new CompositeCanvasPixman());
+    canvas_list.push_back(new CompositeCanvasXRender());
 
 #ifdef USE_EGL
     canvas_list.push_back(new CompositeCanvasEGL());
@@ -156,6 +159,7 @@
     Benchmark::register_test(*new CompositeTestSimpleDefault());
     Benchmark::register_test(*new CompositeTestSimpleBrick());
     Benchmark::register_test(*new CompositeTestPixman());
+    Benchmark::register_test(*new CompositeTestXRender());
 
     // Assign a compatible canvas to each test
     assign_canvas_to_tests(canvas_list);

=== modified file 'src/wscript_build'
--- src/wscript_build	2011-07-18 15:00:13 +0000
+++ src/wscript_build	2011-08-03 17:03:48 +0000
@@ -6,7 +6,7 @@
 glx_sources = ['composite-canvas-glx.cc', 'composite-window-glxpixmap.cc']
 egl_sources = ['composite-canvas-egl.cc', 'composite-window-eglimage.cc']
 
-common_libs = ['x11', 'xdamage', 'xcomposite', 'pixman', 'xext']
+common_libs = ['x11', 'xdamage', 'xcomposite', 'pixman', 'xext', 'xrender']
 
 if bld.env.BUILD_EGL_GL or bld.env.BUILD_GLX:
     bld(

=== modified file 'wscript'
--- wscript	2011-07-21 09:50:35 +0000
+++ wscript	2011-08-18 07:56:25 +0000
@@ -4,7 +4,7 @@
 out = 'build'
 top = '.'
 
-VERSION = '2011.07'
+VERSION = '2011.08'
 APPNAME = 'glcompbench'
 
 def option_list_cb(option, opt, value, parser):
@@ -63,7 +63,7 @@
     # Check required packages
     req_pkgs = [('x11', 'x11'), ('xdamage', 'xdamage'),
                 ('xcomposite', 'xcomposite'), ('pixman-1', 'pixman'),
-                ('xext', 'xext')]
+                ('xext', 'xext'), ('xrender', 'xrender')]
     for (pkg, uselib) in req_pkgs:
         ctx.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs',
                 mandatory = True)

