=== modified file 'src/benchmark.h'
--- src/benchmark.h	2011-06-22 11:35:50 +0000
+++ src/benchmark.h	2011-07-15 10:20:09 +0000
@@ -43,6 +43,8 @@
     CompositeTest &setup_test();
     void teardown_test();
 
+    CompositeTest &get_test() { return test_; }
+
     static void register_test(CompositeTest &test);
     static CompositeTest &get_test_by_name(const std::string &name);
     static const std::map<std::string, CompositeTest *> &tests() { return test_map_; }

=== modified file 'src/composite-canvas-egl.cc'
--- src/composite-canvas-egl.cc	2011-06-24 15:51:40 +0000
+++ src/composite-canvas-egl.cc	2011-07-15 13:01:34 +0000
@@ -256,6 +256,20 @@
     return true;
 }
 
+void
+CompositeCanvasEGL::release_resources()
+{
+    eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                   EGL_NO_CONTEXT);
+    eglDestroySurface(egl_display_, egl_surface_);
+    eglDestroyContext(egl_display_, egl_context_);
+    eglTerminate(egl_display_);
+
+    egl_display_ = 0;
+    egl_config_ = 0;
+    egl_context_ = 0;
+    egl_surface_ = 0;
+}
 
 CompositeWindow *
 CompositeCanvasEGL::create_window(Window win)

=== modified file 'src/composite-canvas-egl.h'
--- src/composite-canvas-egl.h	2011-06-24 15:51:40 +0000
+++ src/composite-canvas-egl.h	2011-07-15 13:01:34 +0000
@@ -31,7 +31,7 @@
 {
 public:
     CompositeCanvasEGL() :
-        CompositeCanvas(),
+        CompositeCanvas("gl"),
         egl_display_(0), egl_config_(0),
         egl_context_(0), egl_surface_(0),
         use_accel_tfp_(false) {}
@@ -41,6 +41,7 @@
 protected:
     XVisualInfo *get_canvas_xvisualinfo();
     bool make_current();
+    void release_resources();
     CompositeWindow *create_window(Window win);
     void update_screen();
 

=== modified file 'src/composite-canvas-glx.cc'
--- src/composite-canvas-glx.cc	2011-06-24 15:51:40 +0000
+++ src/composite-canvas-glx.cc	2011-07-15 13:01:34 +0000
@@ -201,6 +201,13 @@
     return true;
 }
 
+void
+CompositeCanvasGLX::release_resources()
+{
+    glx_fbconfig_ = 0;
+    glXDestroyContext(xdpy_, glx_context_);
+    glx_context_ = 0;
+}
 
 CompositeWindow *
 CompositeCanvasGLX::create_window(Window win)

=== modified file 'src/composite-canvas-glx.h'
--- src/composite-canvas-glx.h	2011-06-24 15:51:40 +0000
+++ src/composite-canvas-glx.h	2011-07-15 13:01:34 +0000
@@ -31,7 +31,7 @@
 {
 public:
     CompositeCanvasGLX() :
-        CompositeCanvas(),
+        CompositeCanvas("gl"),
         glx_fbconfig_(0), glx_context_(0),
         use_accel_tfp_(false) {}
 
@@ -40,6 +40,7 @@
 protected:
     XVisualInfo *get_canvas_xvisualinfo();
     bool make_current();
+    void release_resources();
     CompositeWindow *create_window(Window win);
     void update_screen();
 

=== added file 'src/composite-canvas-pixman.cc'
--- src/composite-canvas-pixman.cc	1970-01-01 00:00:00 +0000
+++ src/composite-canvas-pixman.cc	2011-07-19 08:08:54 +0000
@@ -0,0 +1,254 @@
+/*
+ * 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-pixman.h"
+#include "composite-window-pixman.h"
+#include "options.h"
+#include "log.h"
+
+#include <sys/shm.h>
+
+CompositeCanvasPixman::~CompositeCanvasPixman()
+{
+    release_resources();
+}
+
+bool
+CompositeCanvasPixman::have_xshm()
+{
+    int ignore, major, minor;
+    Bool pixmaps;
+    bool have_xshm = false;
+        
+    /* Check for the XShm extension */
+    if (XQueryExtension(xdpy_, "MIT-SHM", &ignore, &ignore, &ignore)) {
+        if (XShmQueryVersion(xdpy_, &major, &minor, &pixmaps) == True) {
+            Log::debug("XShm extension version %d.%d %s shared pixmaps\n",
+                       major, minor, (pixmaps == True) ? "with" : "without");
+            have_xshm = true;
+        }
+    }
+
+    if (!have_xshm && Options::use_accel_tfp) {
+        Log::info("*** Accelerated TFP requested but X Server doesn't support XSHM\n",
+                  "    Using normal XImage transfer mechanism.");
+    }
+
+    return have_xshm;
+}
+
+bool
+CompositeCanvasPixman::ensure_ximage_shm()
+{
+    XWindowAttributes canvas_attr;
+
+    if (!XGetWindowAttributes(xdpy_, canvas_, &canvas_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    ximage_ = XShmCreateImage(xdpy_, canvas_attr.visual, canvas_attr.depth,
+                              ZPixmap, 0, &shm_info_, width_, height_);
+    if (!ximage_) {
+        Log::error("XCreateImage failed!\n");
+        return false;
+    }
+    
+    /* Get shared memory from the system */
+    shm_info_.shmid = shmget(IPC_PRIVATE, ximage_->bytes_per_line * ximage_->height,
+                             IPC_CREAT | 0777);
+    if (shm_info_.shmid < 0) {
+        Log::error("shmget failed!\n");
+        release_resources();
+        return false;
+    }
+
+    /* Attach shared memory to process address space and set it as RW */
+    shm_info_.readOnly = False;
+    shm_info_.shmaddr = (char *)shmat(shm_info_.shmid, 0, 0);
+    if (shm_info_.shmaddr == reinterpret_cast<char *>(-1)) {
+        Log::error("shmat failed!\n");
+        release_resources();
+        return false;
+    }
+
+    /* Set shared memory as the pixel data for the XImage*/
+    ximage_->data = shm_info_.shmaddr;
+        
+    /* Attach shared memory to X Server */
+    if (!XShmAttach(xdpy_, &shm_info_)) {
+        Log::error("XShmAttach failed!\n");
+        release_resources();
+        return false;
+    }
+
+    return true;
+}
+
+bool
+CompositeCanvasPixman::ensure_ximage()
+{
+    XWindowAttributes canvas_attr;
+
+    if (!XGetWindowAttributes(xdpy_, canvas_, &canvas_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    char *pixel_data = reinterpret_cast<char *>(calloc(4 * width_ * height_, 1));
+
+    ximage_ = XCreateImage(xdpy_, canvas_attr.visual, canvas_attr.depth,
+                           ZPixmap, 0, pixel_data, width_, height_, 32, 0);
+    if (!ximage_) {
+        Log::error("XCreateImage failed!\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool
+CompositeCanvasPixman::ensure_pixman_image()
+{
+    if (pixman_image_)
+        return true;
+
+    bool have_ximage;
+
+    if (use_shm_)
+        have_ximage = ensure_ximage_shm();
+    else
+        have_ximage = ensure_ximage();
+
+    if (!have_ximage)
+        return false;
+
+    gc_ =  XCreateGC(xdpy_, canvas_, 0, 0);
+    if (!gc_) {
+        Log::error("XCreateGC failed!\n");
+        release_resources();
+        return false;
+    }
+
+    pixman_image_ = pixman_image_create_bits(PIXMAN_a8r8g8b8, width_, height_,
+                                             reinterpret_cast<uint32_t *>(ximage_->data),
+                                             4 * width_);
+    if (!pixman_image_) {
+        Log::error("XCreateImage failed!\n");
+        release_resources();
+        return false;
+    }
+
+    return true;
+}
+
+XVisualInfo *
+CompositeCanvasPixman::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
+CompositeCanvasPixman::reshape(int width, int height)
+{
+    CompositeCanvas::reshape(width, height);
+
+    release_resources();
+    ensure_pixman_image();
+}
+
+bool
+CompositeCanvasPixman::make_current()
+{
+    use_shm_ = have_xshm() && Options::use_accel_tfp;
+
+    return ensure_pixman_image();
+}
+
+void
+CompositeCanvasPixman::release_resources()
+{
+    if (pixman_image_)
+        pixman_image_unref(pixman_image_);
+
+    if (gc_)
+        XFreeGC(xdpy_, gc_);
+
+    if (ximage_)
+        XDestroyImage(ximage_);
+
+    if (shm_info_.shmaddr != reinterpret_cast<char *>(-1)) {
+        shmdt(shm_info_.shmaddr);
+        XShmDetach(xdpy_, &shm_info_);
+    }
+
+    pixman_image_ = 0;
+    gc_ = 0;
+    ximage_ = 0;
+    shm_info_.shmaddr = reinterpret_cast<char *>(-1);
+}
+
+CompositeWindow *
+CompositeCanvasPixman::create_window(Window win)
+{
+    return new CompositeWindowPixman(xdpy_, win);
+}
+
+void
+CompositeCanvasPixman::update_screen()
+{
+    if (use_shm_) {
+        XShmPutImage(xdpy_, canvas_, gc_, ximage_, 0, 0, 0, 0, width_,
+                     height_, False);
+    }
+    else {
+        XPutImage(xdpy_, canvas_, gc_, ximage_, 0, 0, 0, 0, width_, height_);
+    }
+}
+
+std::string
+CompositeCanvasPixman::info_string()
+{
+    std::stringstream ss;
+
+    ss << "    Pixman " << pixman_version_string() << std::endl;
+
+    return ss.str();
+}

=== added file 'src/composite-canvas-pixman.h'
--- src/composite-canvas-pixman.h	1970-01-01 00:00:00 +0000
+++ src/composite-canvas-pixman.h	2011-07-18 15:00:13 +0000
@@ -0,0 +1,68 @@
+/*
+ * 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_PIXMAN_H_
+#define COMPOSITE_CANVAS_PIXMAN_H_
+
+#include <pixman.h>
+#include "composite-canvas.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/XShm.h>
+
+class CompositeCanvasPixman: public CompositeCanvas
+{
+public:
+    CompositeCanvasPixman() :
+        CompositeCanvas("pixman"), pixman_image_(0), gc_(0), ximage_(0),
+        use_shm_(false)
+    { shm_info_.shmaddr = reinterpret_cast<char *>(-1); }
+
+    virtual ~CompositeCanvasPixman();
+
+    std::string info_string();
+    pixman_image_t *pixman_image() { return pixman_image_; }
+
+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 ensure_pixman_image();
+    bool ensure_ximage();
+    bool ensure_ximage_shm();
+    bool have_xshm();
+
+    pixman_image_t *pixman_image_;
+    GC gc_;
+    XImage *ximage_;
+    bool use_shm_;
+    XShmSegmentInfo shm_info_;
+};
+
+#endif /* COMPOSITE_CANVAS_PIXMAN_H_ */

=== modified file 'src/composite-canvas.cc'
--- src/composite-canvas.cc	2011-06-28 08:31:16 +0000
+++ src/composite-canvas.cc	2011-07-18 13:28:08 +0000
@@ -135,6 +135,23 @@
 }
 
 /**
+ * Removes all windows from the list of tracked windows.
+ */
+void
+CompositeCanvas::remove_all_windows()
+{
+    for(std::list<CompositeWindow*>::iterator iter = window_list_.begin();
+        iter != window_list_.end(); ++iter)
+    {
+            delete *iter;
+    }
+
+    window_list_.clear();
+
+    return;
+}
+
+/**
  * Updates a window.
  *
  * @param win the Window XID
@@ -349,7 +366,7 @@
     XEvent event;
     bool needs_redraw(false);
     Window window(0);
-    Profiler::ScopedSamples xevent_scoped(profiler_xevent_pair_);
+    Profiler::ScopedSamples xevent_scoped(CompositeCanvas::profiler_xevent_pair());
 
     if (Options::idle_redraw && !XPending(xdpy_))
         return true;
@@ -430,7 +447,7 @@
         iter != window_list_.end(); ++iter)
     {
         CompositeWindow *comp_win = *iter;
-        if (comp_win->get_texture())
+        if (comp_win->get_texture().is_valid())
             comp_win->update_texture_from_pixmap(false);
     }
 }
@@ -438,7 +455,14 @@
 void
 CompositeCanvas::benchmark_init()
 {
-    profiler_cycle_pair_.sample_start();
+    // Ensure that the profiler pairs have been created
+    CompositeCanvas::profiler_cycle_pair();
+    CompositeCanvas::profiler_xevent_pair();
+    CompositeCanvas::profiler_draw_pair();
+    CompositeCanvas::profiler_screen_update_pair();
+
+    Profiler::instance().reset();
+    CompositeCanvas::profiler_cycle_pair().sample_start();
 }
 
 void
@@ -450,10 +474,10 @@
 
     Profiler &profiler = Profiler::instance();
 
-    profiler_cycle_pair_.sample_end();
-    profiler_cycle_pair_.sample_start();
+    CompositeCanvas::profiler_cycle_pair().sample_end();
+    CompositeCanvas::profiler_cycle_pair().sample_start();
 
-    profiler_cycle_pair_.get_stats(stats);
+    CompositeCanvas::profiler_cycle_pair().get_stats(stats);
 
     // Each iteration is 3 seconds of compositing by the current test object.
     // When we complete an iteration, reset the count and tell the caller.
@@ -500,15 +524,6 @@
     }
 }
 
-static void
-next_benchmark(std::list<Benchmark*>& benchmarks,
-               std::list<Benchmark*>::iterator &benchIt)
-{
-    benchIt++;
-    if (benchIt == benchmarks.end() && Options::run_forever)
-        benchIt = benchmarks.begin();
-}
-
 /******************
  * Public methods *
  ******************/
@@ -551,6 +566,24 @@
 }
 
 /**
+ * Deinitializes the canvas.
+ */
+void
+CompositeCanvas::deinit()
+{
+    remove_all_windows();
+    release_resources();
+
+    XDestroyWindow(xdpy_, canvas_);
+    XCloseDisplay(xdpy_);
+
+    xdpy_ = 0;
+    canvas_ = 0;
+    width_ = 0;
+    height_ = 0;
+}
+
+/**
  * Runs a list of tests.
  *
  * @param benchmarks the list of benchmarks to run
@@ -572,19 +605,18 @@
 
     XMapWindow(xdpy_, canvas_);
 
-    // Initialize all tests so that the benchmarking is not biased by
+    // Initialize tests to run so that the benchmarking is not biased by
     // setup time (loading and building shaders, etc.)
-    for (std::map<std::string, CompositeTest*>::const_iterator testIt =
-            Benchmark::tests().begin();
-         testIt != Benchmark::tests().end();
-         testIt++)
+    for (std::list<Benchmark *>::iterator benchIt = benchmarks.begin();
+         benchIt != benchmarks.end();
+         benchIt++)
     {
-        CompositeTest* curTest = testIt->second;
-        if (!curTest) {
-            Log::error("Found a NULL test pointer!\n");
+        Benchmark *benchmark = *benchIt;
+        if (!benchmark) {
+            Log::error("Found a NULL benchmark pointer!\n");
             return;
         }
-        curTest->init();
+        benchmark->get_test().init();
     }
 
     benchmark_init();
@@ -593,14 +625,14 @@
 
     for (std::list<Benchmark *>::iterator benchIt = benchmarks.begin();
          benchIt != benchmarks.end();
-         next_benchmark(benchmarks, benchIt))
+         benchIt++)
     {
         Benchmark *benchmark = *benchIt;
         current_test_ = &benchmark->setup_test();
 
         if (!current_test_->name().empty()) {
             load_current_test_options();
-            reshape(width_, height_);
+            current_test_->reshape(width_, height_);
             Log::info("Running test: '%s'\n", current_test_->name().c_str());
 
             while (true) {
@@ -609,12 +641,12 @@
                         update_all_textures();
 
                     if (Options::draw) {
-                        profiler_draw_pair_.sample_start();
+                        CompositeCanvas::profiler_draw_pair().sample_start();
                         current_test_->draw(this->window_list_);
-                        profiler_draw_pair_.sample_end();
-                        profiler_screen_update_pair_.sample_start();
+                        CompositeCanvas::profiler_draw_pair().sample_end();
+                        CompositeCanvas::profiler_screen_update_pair().sample_start();
                         update_screen();
-                        profiler_screen_update_pair_.sample_end();
+                        CompositeCanvas::profiler_screen_update_pair().sample_end();
                     }
 
                     benchmark_update(next_iteration);
@@ -628,5 +660,18 @@
 
         benchmark->teardown_test();
     }
+
+    // Deinitialize tests
+    for (std::list<Benchmark *>::iterator benchIt = benchmarks.begin();
+         benchIt != benchmarks.end();
+         benchIt++)
+    {
+        Benchmark *benchmark = *benchIt;
+        if (!benchmark) {
+            Log::error("Found a NULL benchmark pointer!\n");
+            return;
+        }
+        benchmark->get_test().deinit();
+    }
 }
 

=== modified file 'src/composite-canvas.h'
--- src/composite-canvas.h	2011-06-24 15:51:40 +0000
+++ src/composite-canvas.h	2011-07-18 13:28:08 +0000
@@ -40,29 +40,33 @@
 class CompositeCanvas
 {
 public:
-    CompositeCanvas():
+    CompositeCanvas(const std::string &type):
         xdpy_(0), root_(0), canvas_(0), damage_event_(0),
-        current_test_(0), iterations_(0), width_(0), height_(0),
-        profiler_cycle_pair_("cycle"),
-        profiler_xevent_pair_("xevent"),
-        profiler_draw_pair_("draw"),
-        profiler_screen_update_pair_("screen-update")
+        width_(0), height_(0), 
+        current_test_(0), iterations_(0), type_(type)
     {}
 
     bool init();
+    void deinit();
     void run_tests(std::list<Benchmark*> &benchmarks);
     virtual std::string info_string() { return std::string(); }
+    
+    const std::string &type() { return type_; }
 
 protected:
     virtual XVisualInfo *get_canvas_xvisualinfo() = 0;
     virtual bool make_current() = 0;
+    virtual void release_resources() = 0;
     virtual CompositeWindow *create_window(Window win) = 0;
     virtual void update_screen() = 0;
+    virtual void reshape(int width, int height);
 
     Display *xdpy_;
     Window root_;
     Window canvas_;
     int damage_event_;
+    unsigned int width_;
+    unsigned int height_;
 
     std::list<CompositeWindow*> window_list_;
     CompositeTest *current_test_;
@@ -71,8 +75,8 @@
     CompositeWindow *find_window(Window win);
     void add_window(Window win);
     void remove_window(Window win);
+    void remove_all_windows();
     void update_window(Window win);
-    void reshape(int width, int height);
     Window create_canvas_x_window(const char *name, int x, int y,
                                   int width, int height,
                                   XVisualInfo *vis_info);
@@ -87,15 +91,35 @@
     void sample_point(int i);
     void load_current_test_options();
     unsigned int iterations_;
-    unsigned int width_;
-    unsigned int height_;
     double current_test_duration_;
     unsigned int current_test_iterations_;
 
-    Profiler::PointPair profiler_cycle_pair_;
-    Profiler::PointPair profiler_xevent_pair_;
-    Profiler::PointPair profiler_draw_pair_;
-    Profiler::PointPair profiler_screen_update_pair_;
+    std::string type_;
+
+    static Profiler::PointPair &profiler_cycle_pair()
+    {
+        static Profiler::PointPair profiler_cycle_pair_("cycle");
+        return profiler_cycle_pair_;
+    }
+
+    static Profiler::PointPair &profiler_xevent_pair()
+    {
+        static Profiler::PointPair profiler_xevent_pair_("xevent");
+        return profiler_xevent_pair_;
+    }
+
+    static Profiler::PointPair &profiler_draw_pair()
+    {
+        static Profiler::PointPair profiler_draw_pair_("draw");
+        return profiler_draw_pair_;
+    }
+
+    static Profiler::PointPair &profiler_screen_update_pair()
+    {
+        static Profiler::PointPair profiler_screen_update_pair_("screen-update");
+        return profiler_screen_update_pair_;
+    }
+
 };
 
 

=== added file 'src/composite-test-pixman.cc'
--- src/composite-test-pixman.cc	1970-01-01 00:00:00 +0000
+++ src/composite-test-pixman.cc	2011-07-18 12:38:37 +0000
@@ -0,0 +1,128 @@
+/*
+ * 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 <pixman.h>
+#include <sstream>
+#include <fstream>
+#include <cstring>
+#include <cstdlib>
+
+#include "composite-test.h"
+#include "composite-canvas-pixman.h"
+#include "options.h"
+#include "log.h"
+
+CompositeTestPixman::CompositeTestPixman() :
+    CompositeTest("pixman", "pixman")
+{
+    options_["filter"] = CompositeTest::Option("filter", "bilinear",
+                                               "Filter to use [nearest, bilinear]");
+}
+
+void
+CompositeTestPixman::init()
+{
+    pixman_color_t half_transparent = {0x7fff, 0x7fff, 0x7fff, 0x7fff};
+    half_transparent_mask_ = pixman_image_create_solid_fill(&half_transparent);
+}
+
+void
+CompositeTestPixman::deinit()
+{
+    if (half_transparent_mask_)
+        pixman_image_unref(half_transparent_mask_);
+}
+
+void
+CompositeTestPixman::prepare_for_run()
+{
+    if (options_["filter"].value == "bilinear")
+        pixman_filter_ = PIXMAN_FILTER_BILINEAR;
+    else
+        pixman_filter_ = PIXMAN_FILTER_NEAREST;
+}
+
+void
+CompositeTestPixman::draw(std::list<CompositeWindow *> &window_list)
+{
+    CompositeCanvasPixman *canvas_pixman =
+        static_cast<CompositeCanvasPixman *>(canvas_);
+
+    pixman_image_t *dest_image = canvas_pixman->pixman_image();
+    int dest_width = pixman_image_get_width(dest_image);
+    int dest_height = pixman_image_get_height(dest_image);
+
+    /* Clear the screen with color matching GL {0.1, 0.1, 0.3, 1.0} */
+    pixman_color_t clear = {6554, 6554, 19661, 65535};
+
+    pixman_box32_t box;
+    box.x1 = box.y1 = 0;
+    box.x2 = dest_width > 0 ? dest_width - 1 : 0;
+    box.y2 = dest_height > 0 ? dest_height - 1 : 0;
+
+    pixman_image_fill_boxes(PIXMAN_OP_SRC, dest_image, &clear, 1, &box);
+
+    /* 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;
+        pixman_image_t *pixman_image = reinterpret_cast<pixman_image_t *>(comp_win->get_texture().p);
+        if (pixman_image) {
+            int width = pixman_image_get_width(pixman_image);
+            int height = pixman_image_get_height(pixman_image);
+
+            /* 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 */
+            pixman_transform_t xform;
+
+            pixman_image_set_filter(pixman_image, pixman_filter_, NULL, 0);
+            pixman_transform_init_scale(&xform,
+                                        pixman_double_to_fixed(2.0 * width / dest_width),
+                                        pixman_double_to_fixed(2.0 * height / dest_height));
+            pixman_image_set_transform(pixman_image, &xform);
+
+            /* Draw the image to the canvas image */
+            pixman_image_composite32(PIXMAN_OP_OVER, pixman_image,
+                                     half_transparent_mask_, dest_image,
+                                     0, 0, 0, 0, x0, y0,
+                                     dest_width / 2, dest_height / 2);
+
+            i++;
+        }
+    }
+}
+
+

=== modified file 'src/composite-test-simple-base.cc'
--- src/composite-test-simple-base.cc	2011-06-24 16:02:39 +0000
+++ src/composite-test-simple-base.cc	2011-07-15 13:08:25 +0000
@@ -21,6 +21,7 @@
  *  Jesse Barker <jesse.barker@linaro.org>
  */
 
+#include "gl-headers.h"
 #include "composite-test.h"
 #include "options.h"
 #include "log.h"
@@ -37,7 +38,7 @@
 CompositeTestSimpleBase::CompositeTestSimpleBase(const std::string& test_name,
                                                  const std::string& vs_filename,
                                                  const std::string& fs_filename)
-    : CompositeTest(test_name), vs_filename_(vs_filename),
+    : CompositeTest(test_name, "gl"), vs_filename_(vs_filename),
       fs_filename_(fs_filename)
 {
     options_["use-vbo"] = CompositeTest::Option("use-vbo", "true",
@@ -47,6 +48,9 @@
 void
 CompositeTestSimpleBase::init()
 {
+    if (initialized_)
+        return;
+
     // Initialize shader sources from input files
     if (!gotSource(vs_filename_, vertex_shader_))
     {
@@ -111,6 +115,8 @@
     vboData_.addTexCoord(vec2(0, 0));
 
     vboData_.genBufferObject();
+
+    initialized_ = true;
 }
 
 /**
@@ -153,3 +159,18 @@
 {
     program_.stop();
 }
+
+void
+CompositeTestSimpleBase::deinit()
+{
+    if (!initialized_)
+        return;
+
+    vertex_shader_.clear();
+    fragment_shader_.clear();
+    vboData_.release();
+    program_.release();
+    vertexIndex_ = 0;
+    texcoordIndex_ = 0;
+    initialized_ = false;
+}

=== modified file 'src/composite-test-simple-brick.cc'
--- src/composite-test-simple-brick.cc	2011-06-23 13:32:36 +0000
+++ src/composite-test-simple-brick.cc	2011-07-15 08:16:54 +0000
@@ -21,6 +21,7 @@
  *  Jesse Barker <jesse.barker@linaro.org>
  */
 
+#include "gl-headers.h"
 #include "composite-test.h"
 #include "options.h"
 #include "log.h"
@@ -75,7 +76,7 @@
         iter != window_list.end(); ++iter)
     {
         CompositeWindow *comp_win = *iter;
-        GLuint tex = comp_win->get_texture();
+        GLuint tex = comp_win->get_texture().i;
         if (tex) {
             model_view_matrix.push();
             model_view_matrix.translate(cos(angular_step * i),

=== modified file 'src/composite-test-simple-default.cc'
--- src/composite-test-simple-default.cc	2011-06-23 11:22:08 +0000
+++ src/composite-test-simple-default.cc	2011-07-15 08:16:54 +0000
@@ -21,6 +21,7 @@
  *  Jesse Barker <jesse.barker@linaro.org>
  */
 
+#include "gl-headers.h"
 #include "composite-test.h"
 #include "options.h"
 #include "log.h"
@@ -56,7 +57,7 @@
         iter != window_list.end(); ++iter)
     {
         CompositeWindow *comp_win = *iter;
-        GLuint tex = comp_win->get_texture();
+        GLuint tex = comp_win->get_texture().i;
         if (tex) {
             model_view_matrix.push();
             model_view_matrix.translate(cos(angular_step * i),

=== modified file 'src/composite-test.cc'
--- src/composite-test.cc	2011-06-24 16:02:39 +0000
+++ src/composite-test.cc	2011-07-15 10:31:48 +0000
@@ -28,8 +28,8 @@
 using std::string;
 using std::map;
 
-CompositeTest::CompositeTest(const string& test_name) :
-    name_(test_name)
+CompositeTest::CompositeTest(const string& test_name, const string& type) :
+    name_(test_name), type_(type), initialized_(false), canvas_(0)
 {
     options_["duration"] = CompositeTest::Option("duration", "3.0",
                                                  "The duration of each iteration in seconds");
@@ -52,7 +52,7 @@
     for(std::list<CompositeWindow*>::iterator iter = window_list.begin();
         iter != window_list.end(); iter++)
     {
-        if ((*iter)->get_texture())
+        if ((*iter)->get_texture().is_valid())
             count++;
     }
 

=== modified file 'src/composite-test.h'
--- src/composite-test.h	2011-07-18 17:14:16 +0000
+++ src/composite-test.h	2011-07-19 08:29:50 +0000
@@ -27,19 +27,22 @@
 #include <string>
 #include <list>
 #include <map>
+#include <pixman.h>
+
 #include "stack.h"
 #include "program.h"
 #include "composite-window.h"
 #include "vbo.h"
 
-class composite_data;
+class CompositeCanvas;
 
 class CompositeTest
 {
 public:
-    CompositeTest(const std::string& test_name);
+    CompositeTest(const std::string& test_name, const std::string &type);
 
     virtual void init() {}
+    virtual void deinit() {}
     virtual void prepare_for_run() {}
     virtual void draw(std::list<CompositeWindow*> &window_list)
     {
@@ -68,9 +71,13 @@
     bool set_option_default(const std::string &opt, const std::string &val);
     const std::map<std::string, Option> &options() { return options_; }
 
+    const std::string &type() { return type_; }
+    void set_canvas(CompositeCanvas *canvas) { canvas_ = canvas; }
+    CompositeCanvas *canvas() { return canvas_; }
+
     static CompositeTest &dummy()
     {
-        static CompositeTest dummy_test("");
+        static CompositeTest dummy_test("", "");
         return dummy_test;
     }
 
@@ -86,12 +93,15 @@
     int num_visible_windows(std::list<CompositeWindow *> &window_list);
     std::string name_;
     std::map<std::string, Option> options_;
+    std::string type_;
+    bool initialized_;
+    CompositeCanvas *canvas_;
 };
 
 class CompositeTestDefaultOptions : public CompositeTest
 {
 public:
-    CompositeTestDefaultOptions() : CompositeTest("") {}
+    CompositeTestDefaultOptions() : CompositeTest("", "") {}
 
     virtual void prepare_for_run();
     virtual bool set_option(const std::string &opt, const std::string &val);
@@ -108,6 +118,7 @@
                             const std::string& fs_filename);
 
     virtual void init();
+    virtual void deinit();
     virtual void prepare_for_run();
     virtual void cleanup();
     virtual void reshape(int width, int height);
@@ -166,4 +177,19 @@
     static const std::string lightPosName_;
 };
 
+class CompositeTestPixman : public CompositeTest
+{
+public:
+    CompositeTestPixman();
+
+    virtual void init();
+    virtual void deinit();
+    virtual void prepare_for_run();
+    virtual void draw(std::list<CompositeWindow*> &window_list);
+
+private:
+    pixman_image_t *half_transparent_mask_;
+    pixman_filter_t pixman_filter_;
+};
+
 #endif // COMPOSITE_TEST_H_

=== modified file 'src/composite-window-eglimage.h'
--- src/composite-window-eglimage.h	2011-02-07 18:41:00 +0000
+++ src/composite-window-eglimage.h	2011-07-15 08:16:54 +0000
@@ -28,14 +28,14 @@
 #include "gl-headers.h"
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include "composite-window.h"
+#include "composite-window-gl.h"
 
-class CompositeWindowEGLImage : public CompositeWindow
+class CompositeWindowEGLImage : public CompositeWindowGL
 {
 public:
     CompositeWindowEGLImage(Display *xdpy, Window win,
                             EGLDisplay egl_display) :
-        CompositeWindow(xdpy, win),
+        CompositeWindowGL(xdpy, win),
         egl_image_(0), egl_display_(egl_display) {}
     ~CompositeWindowEGLImage();
 

=== added file 'src/composite-window-gl.cc'
--- src/composite-window-gl.cc	1970-01-01 00:00:00 +0000
+++ src/composite-window-gl.cc	2011-07-15 08:16:54 +0000
@@ -0,0 +1,58 @@
+/*
+ * 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 "composite-window-gl.h"
+#include "log.h"
+
+CompositeWindowGL::~CompositeWindowGL()
+{
+    if (tex_)
+        glDeleteTextures(1, &tex_);
+}
+
+bool
+CompositeWindowGL::update_texture()
+{
+    bool ret = false;
+
+    if (!tex_ && attr_.map_state != 0) {
+        glGenTextures(1, &tex_);
+
+        glBindTexture(GL_TEXTURE_2D, tex_);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        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;
+}
+

=== added file 'src/composite-window-gl.h'
--- src/composite-window-gl.h	1970-01-01 00:00:00 +0000
+++ src/composite-window-gl.h	2011-07-15 08:16:54 +0000
@@ -0,0 +1,45 @@
+/*
+ * 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_GL_H_
+#define COMPOSITE_WINDOW_GL_H_
+
+#include "gl-headers.h"
+#include "composite-window.h"
+
+class CompositeWindowGL : public CompositeWindow
+{
+public:
+    CompositeWindowGL(Display *xdpy, Window win) :
+        CompositeWindow(xdpy, win), tex_(0) {}
+
+    virtual ~CompositeWindowGL();
+
+    virtual Texture get_texture() { return CompositeWindow::Texture(tex_); }
+    virtual bool update_texture();
+
+protected:
+    GLuint tex_;
+};
+
+#endif /* COMPOSITE_WINDOW_GL_H_ */

=== modified file 'src/composite-window-glxpixmap.h'
--- src/composite-window-glxpixmap.h	2011-02-07 18:00:40 +0000
+++ src/composite-window-glxpixmap.h	2011-07-15 08:16:54 +0000
@@ -26,14 +26,14 @@
 
 #include <X11/Xlib.h>
 #include <GL/glx.h>
-#include "composite-window.h"
+#include "composite-window-gl.h"
 
-class CompositeWindowGLXPixmap : public CompositeWindow
+class CompositeWindowGLXPixmap : public CompositeWindowGL
 {
 public:
     CompositeWindowGLXPixmap(Display *xdpy, Window win,
                              GLXFBConfig glx_fbconfig) :
-        CompositeWindow(xdpy, win), glx_pixmap_(0),
+        CompositeWindowGL(xdpy, win), glx_pixmap_(0),
         glx_fbconfig_ (glx_fbconfig) {}
     ~CompositeWindowGLXPixmap();
 

=== added file 'src/composite-window-pixman.cc'
--- src/composite-window-pixman.cc	1970-01-01 00:00:00 +0000
+++ src/composite-window-pixman.cc	2011-07-18 16:26:56 +0000
@@ -0,0 +1,201 @@
+/*
+ * 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 <cstdlib>
+
+#include "gl-headers.h"
+
+#include "composite-window-pixman.h"
+#include "log.h"
+
+CompositeWindowPixman::~CompositeWindowPixman()
+{
+    release_resources();
+}
+
+void
+CompositeWindowPixman::release_resources()
+{
+    if (ximage_)
+        XDestroyImage(ximage_);
+
+    if (pixman_image_)
+        pixman_image_unref(pixman_image_);
+
+    if (shm_info_.shmaddr != reinterpret_cast<char *>(-1)) {
+        shmdt(shm_info_.shmaddr);
+        XShmDetach(xdpy_, &shm_info_);
+    }
+
+    ximage_ = 0;
+    pixman_image_ = 0;
+    shm_info_.shmaddr = reinterpret_cast<char *>(-1);
+}
+
+bool
+CompositeWindowPixman::have_xshm()
+{
+    int ignore, major, minor;
+    Bool pixmaps;
+    bool have_xshm = false;
+        
+    if (XQueryExtension(xdpy_, "MIT-SHM", &ignore, &ignore, &ignore)
+        && XShmQueryVersion(xdpy_, &major, &minor, &pixmaps) == True)
+    {
+        have_xshm = true;
+    }
+
+    return have_xshm;
+}
+
+bool
+CompositeWindowPixman::ensure_ximage_shm()
+{
+    if (ximage_)
+        return true;
+
+    XWindowAttributes win_attr;
+
+    if (!XGetWindowAttributes(xdpy_, win_, &win_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    ximage_ = XShmCreateImage(xdpy_, win_attr.visual, win_attr.depth,
+                              ZPixmap, 0, &shm_info_, width_, height_);
+    if (!ximage_) {
+        Log::error("XCreateImage failed!\n");
+        return false;
+    }
+    
+    /* Get shared memory from the system */
+    shm_info_.shmid = shmget(IPC_PRIVATE, ximage_->bytes_per_line * ximage_->height,
+                             IPC_CREAT | 0777);
+    if (shm_info_.shmid < 0) {
+        Log::error("shmget failed!\n");
+        release_resources();
+        return false;
+    }
+
+    /* Attach shared memory to process address space and set it as RW */
+    shm_info_.readOnly = False;
+    shm_info_.shmaddr = (char *)shmat(shm_info_.shmid, 0, 0);
+    if (shm_info_.shmaddr == reinterpret_cast<char *>(-1)) {
+        Log::error("shmat failed!\n");
+        release_resources();
+        return false;
+    }
+
+    /* Set shared memory as the pixel data for the XImage*/
+    ximage_->data = shm_info_.shmaddr;
+        
+    /* Attach shared memory to X Server */
+    if (!XShmAttach(xdpy_, &shm_info_)) {
+        Log::error("XShmAttach failed!\n");
+        release_resources();
+        return false;
+    }
+
+    return true;
+}
+
+bool
+CompositeWindowPixman::ensure_ximage()
+{
+    if (ximage_)
+        return true;
+
+    XWindowAttributes win_attr;
+
+    if (!XGetWindowAttributes(xdpy_, win_, &win_attr)) {
+        Log::error("XGetWindowAttributes failed!\n");
+        return false;
+    }
+
+    char *pixel_data = reinterpret_cast<char *>(calloc(4 * width_ * height_, 1));
+
+    ximage_ = XCreateImage(xdpy_, win_attr.visual, win_attr.depth,
+                           ZPixmap, 0, pixel_data, width_, height_, 32, 0);
+    if (!ximage_) {
+        Log::error("XCreateImage failed!\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool
+CompositeWindowPixman::ensure_pixman_image()
+{
+    if (pixman_image_)
+        return true;
+
+    pixman_format_code_t format =
+        static_cast<pixman_format_code_t>(
+            PIXMAN_FORMAT(ximage_->bits_per_pixel,
+                          PIXMAN_TYPE_ARGB,
+                          ximage_->depth - 24, 8, 8, 8));
+
+    if (!pixman_format_supported_source(format)) {
+        Log::debug("Source pixmap format is not supported by pixman!");
+    }
+    else {
+        pixman_image_ = pixman_image_create_bits(format, width_, height_,
+                                                 reinterpret_cast<uint32_t *>(ximage_->data),
+                                                 width_ * 4);
+    }
+
+    return pixman_image_ != 0;
+}
+
+void
+CompositeWindowPixman::update_texture_from_pixmap(bool recreate)
+{
+    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;
+}

=== added file 'src/composite-window-pixman.h'
--- src/composite-window-pixman.h	1970-01-01 00:00:00 +0000
+++ src/composite-window-pixman.h	2011-07-18 16:26:56 +0000
@@ -0,0 +1,66 @@
+/*
+ * 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/XShm.h>
+#include <sys/shm.h>
+#include <pixman.h>
+
+#include "composite-window.h"
+#include "options.h"
+
+class CompositeWindowPixman : public CompositeWindow
+{
+public:
+    CompositeWindowPixman(Display *xdpy, Window win) :
+        CompositeWindow(xdpy, win), pixman_image_(0), ximage_(0),
+        use_shm_(have_xshm() && Options::use_accel_tfp)
+        { shm_info_.shmaddr = reinterpret_cast<char *>(-1); }
+
+    ~CompositeWindowPixman();
+
+    CompositeWindow::Texture get_texture()
+    {
+        return CompositeWindow::Texture(pixman_image_);
+    }
+
+    bool update_texture();
+    void update_texture_from_pixmap(bool recreate);
+
+private:
+    bool have_xshm();
+    bool ensure_ximage();
+    bool ensure_ximage_shm();
+    bool ensure_pixman_image();
+    void release_resources();
+
+    pixman_image_t *pixman_image_;
+    XImage *ximage_;
+    bool use_shm_;
+    XShmSegmentInfo shm_info_;
+};
+
+#endif

=== modified file 'src/composite-window-ximage.h'
--- src/composite-window-ximage.h	2011-02-07 18:35:50 +0000
+++ src/composite-window-ximage.h	2011-07-15 08:16:54 +0000
@@ -26,13 +26,13 @@
 
 #include <X11/Xlib.h>
 #include "gl-headers.h"
-#include "composite-window.h"
+#include "composite-window-gl.h"
 
-class CompositeWindowXImage : public CompositeWindow
+class CompositeWindowXImage : public CompositeWindowGL
 {
 public:
     CompositeWindowXImage(Display *xdpy, Window win) :
-        CompositeWindow(xdpy, win), ximage_(0) {}
+        CompositeWindowGL(xdpy, win), ximage_(0) {}
     ~CompositeWindowXImage();
 
     void update_texture_from_pixmap(bool recreate);

=== modified file 'src/composite-window.cc'
--- src/composite-window.cc	2011-04-04 12:56:06 +0000
+++ src/composite-window.cc	2011-07-15 08:16:54 +0000
@@ -36,9 +36,6 @@
 
     if (damage_)
         XDamageDestroy(xdpy_, damage_);
-
-    if (tex_)
-        glDeleteTextures(1, &tex_);
 }
 
 /**
@@ -50,7 +47,7 @@
     int x, y;
     unsigned int width, height, border;
     Window root;
-    bool update_texture = false;
+    bool update_tfp = false;
     Pixmap pix_to_free = None;
 
     Log::debug("Composite: Updating window 0x%x\n", (unsigned)win_);
@@ -78,7 +75,7 @@
     if (!pix_ && attr_.map_state != 0) {
         pix_ = XCompositeNameWindowPixmap(xdpy_, win_);
         Log::debug("    => Pixmap <= 0x%x\n", (unsigned) pix_);
-        update_texture = true;
+        update_tfp = true;
     }
     else if (pix_ && attr_.map_state == 0) {
         Log::debug("    => Destroying Pixmap 0x%x\n", (unsigned) pix_);
@@ -99,25 +96,9 @@
     }
 
     /* Create or delete texture if needed */
-    if (!tex_ && attr_.map_state != 0) {
-        glGenTextures(1, &tex_);
-
-        glBindTexture(GL_TEXTURE_2D, tex_);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-        Log::debug("    => texture <= 0x%x\n", (unsigned) tex_);
-        update_texture = true;
-    }
-    else if (tex_ && attr_.map_state == 0) {
-        Log::debug("    => Deleting texture 0x%x\n", (unsigned) tex_);
-        glDeleteTextures(1, &tex_);
-        tex_ = 0;
-    }
-
-    if (update_texture)
+    update_tfp = update_texture() || update_tfp;
+
+    if (update_tfp)
         update_texture_from_pixmap(true);
 
     /*
@@ -136,12 +117,6 @@
     return win_;
 }
 
-GLuint
-CompositeWindow::get_texture()
-{
-    return tex_;
-}
-
 void
 CompositeWindow::handle_damage()
 {

=== modified file 'src/composite-window.h'
--- src/composite-window.h	2011-04-04 12:56:06 +0000
+++ src/composite-window.h	2011-07-15 08:16:54 +0000
@@ -26,7 +26,6 @@
 
 #include <X11/Xlib.h>
 #include <X11/extensions/Xdamage.h>
-#include "gl-headers.h"
 #include "profiler.h"
 
 class CompositeWindow
@@ -34,14 +33,23 @@
 public:
     CompositeWindow(Display *xdpy, Window win) :
         xdpy_(xdpy), win_(win), pix_(0), damage_(0),
-        tex_(0), width_(0), height_(0), depth_(0) {}
+        width_(0), height_(0), depth_(0) {}
+
+    union Texture {
+        Texture(void *p): p(p) {}
+        Texture(unsigned int i): i(i) {}
+        bool is_valid() { return p != 0 && i != 0; }
+        void *p;
+        unsigned int i;
+    };
 
     virtual ~CompositeWindow();
     void update();
     void handle_damage();
     Window get_xwindow();
-    GLuint get_texture();
 
+    virtual Texture get_texture() = 0;
+    virtual bool update_texture() = 0;
     virtual void update_texture_from_pixmap(bool recreate) = 0;
 
 protected:
@@ -50,7 +58,6 @@
     Pixmap pix_;
     Damage damage_;
     XWindowAttributes attr_;
-    GLuint tex_;
 
     unsigned int width_;
     unsigned int height_;

=== modified file 'src/glcompbench.cc'
--- src/glcompbench.cc	2011-06-24 15:51:40 +0000
+++ src/glcompbench.cc	2011-07-19 08:18:28 +0000
@@ -28,6 +28,7 @@
 #elif USE_GLX
 #include "composite-canvas-glx.h"
 #endif
+#include "composite-canvas-pixman.h"
 
 #include "composite-test.h"
 #include "benchmark.h"
@@ -37,6 +38,7 @@
 static const char *default_benchmarks[] = {
     "default",
     "brick",
+    "pixman",
     NULL
 };
 
@@ -91,13 +93,53 @@
     }
 }
 
+void
+assign_canvas_to_tests(std::list<CompositeCanvas *> &canvas_list)
+{
+    const map<string, CompositeTest *> &tests = Benchmark::tests();
+
+    for (map<string, CompositeTest *>::const_iterator test_iter = tests.begin();
+         test_iter != tests.end();
+         test_iter++)
+
+    {
+        CompositeTest *test = test_iter->second;
+        if (test->type().empty())
+            continue;
+
+        for (std::list<CompositeCanvas *>::const_iterator iter = canvas_list.begin();
+             iter != canvas_list.end();
+             iter++)
+        {
+            CompositeCanvas *canvas = *iter;
+            if (canvas->type() == test->type()) {
+                test->set_canvas(canvas);
+                break;
+            }
+        }
+    }
+}
+
+static void
+next_benchmark(std::list<Benchmark*>& benchmarks,
+               std::list<Benchmark*>::const_iterator &benchIt)
+{
+    benchIt++;
+    if (benchIt == benchmarks.end() && Options::run_forever)
+        benchIt = benchmarks.begin();
+}
+
+
 int
 main(int argc, char **argv)
 {
+    std::list<CompositeCanvas *> canvas_list;
+    canvas_list.push_back(new CompositeCanvasPixman());
+
 #ifdef USE_EGL
-    CompositeCanvasEGL canvas;
+    canvas_list.push_back(new CompositeCanvasEGL());
 #elif USE_GLX
-    CompositeCanvasGLX canvas;
+    canvas_list.push_back(new CompositeCanvasGLX());
 #endif
 
     std::list<Benchmark*> benchmarks;
@@ -113,6 +155,10 @@
     Benchmark::register_test(*new CompositeTestDefaultOptions());
     Benchmark::register_test(*new CompositeTestSimpleDefault());
     Benchmark::register_test(*new CompositeTestSimpleBrick());
+    Benchmark::register_test(*new CompositeTestPixman());
+
+    // Assign a compatible canvas to each test
+    assign_canvas_to_tests(canvas_list);
 
     if (Options::list_tests) {
         list_tests();
@@ -125,15 +171,54 @@
     else
         add_custom_benchmarks(benchmarks);
 
-    canvas.init();
 
     Log::info("=======================================================\n");
     Log::info("    glcompbench %s\n", GLCOMPBENCH_VERSION);
-    Log::info("=======================================================\n");
-    Log::info("%s", canvas.info_string().c_str());
-    Log::info("=======================================================\n");
-
-    canvas.run_tests(benchmarks);
+
+    CompositeCanvas *canvas = 0;
+    std::list<Benchmark *> current_benchmarks;
+
+    // Find continuous runs of benchmarks that use the same canvas
+    // and run them together
+    for (std::list<Benchmark *>::const_iterator iter = benchmarks.begin();
+         iter != benchmarks.end();
+         next_benchmark(benchmarks, iter))
+    {
+        Benchmark *benchmark = *iter;
+        CompositeCanvas *test_canvas = benchmark->get_test().canvas();
+
+        // Check the canvas of the next benchmark (if any)
+        std::list<Benchmark *>::const_iterator next_iter = iter;
+        next_iter++;
+        CompositeCanvas *next_canvas = next_iter == benchmarks.end() ? 0 :
+                                       (*next_iter)->get_test().canvas();
+
+        // If we have a change in canvas, deinit the previous one
+        // and init the new
+        if (test_canvas != canvas && test_canvas != 0) {
+            if (canvas)
+                canvas->deinit();
+            canvas = test_canvas;
+            canvas->init();
+            Log::info("=======================================================\n");
+            Log::info("%s", canvas->info_string().c_str());
+            Log::info("=======================================================\n");
+        }
+
+        current_benchmarks.push_back(benchmark);
+
+        // We should run the current benchmarks if we have reached the end
+        // or the next benchmark will cause a change to a new valid canvas
+        bool should_run = canvas &&
+                          (next_iter == benchmarks.end() ||
+                           (next_canvas != 0 && next_canvas != canvas));
+
+        if (should_run) {
+            canvas->run_tests(current_benchmarks);
+            current_benchmarks.clear();
+        }
+
+    }
 
     return 0;
 }

=== modified file 'src/vbo.cc'
--- src/vbo.cc	2011-04-27 17:46:24 +0000
+++ src/vbo.cc	2011-07-15 13:03:49 +0000
@@ -257,3 +257,14 @@
     glDrawElements(GL_TRIANGLES, indexData_.count(), GL_UNSIGNED_SHORT,
         indexOffset());
 }
+
+void
+VertexBufferData::release()
+{
+    vertexData_.clear();
+    texcoordData_.clear();
+    indexData_.clear();
+    glDeleteBuffers(2, &bufferObjects_[0]);
+    useBufferObjects_ = false;
+    isMutable_ = false;
+}

=== modified file 'src/vbo.h'
--- src/vbo.h	2011-04-27 17:46:24 +0000
+++ src/vbo.h	2011-07-15 13:03:49 +0000
@@ -36,6 +36,7 @@
     void addVertex(const LibMatrix::vec3& v) { vertexVec_.push_back(v); }
     unsigned int count() const { return vertexVec_.size(); }
     const LibMatrix::vec3* data() const { return vertexVec_.data(); }
+    void clear() { vertexVec_.clear(); }
 private:
     std::vector<LibMatrix::vec3> vertexVec_;
 };
@@ -49,6 +50,7 @@
     void addIndex(const unsigned short i) { indexVec_.push_back(i); }
     unsigned int count() const { return indexVec_.size(); }
     const unsigned short* data() { return indexVec_.data(); }
+    void clear() { indexVec_.clear(); }
 private:
     std::vector<unsigned short> indexVec_;
 };
@@ -62,6 +64,7 @@
     void addTexCoord(const LibMatrix::vec2& t) { texcoordVec_.push_back(t); }
     unsigned int count() const { return texcoordVec_.size(); }
     const LibMatrix::vec2* data() const { return texcoordVec_.data(); }
+    void clear() { texcoordVec_.clear(); }
 private:
     std::vector<LibMatrix::vec2> texcoordVec_;
 };
@@ -105,6 +108,8 @@
     void unbind();
     // Draw the object(s) described by the current data.
     void draw();
+    // Release all resources held by this object
+    void release();
     // Used to specifiy pointers to glVertexAttribPointer(), etc.
     const void* texcoordOffset() const { return reinterpret_cast<const void*>(dataMap_.texcoordOffset); }
     const void* vertexOffset() const { return reinterpret_cast<const void*>(dataMap_.vertexOffset); }

=== modified file 'src/wscript_build'
--- src/wscript_build	2011-06-22 08:59:00 +0000
+++ src/wscript_build	2011-07-18 15:00:13 +0000
@@ -6,6 +6,8 @@
 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']
+
 if bld.env.BUILD_EGL_GL or bld.env.BUILD_GLX:
     bld(
         features = ['cxx', 'cxxstlib'],
@@ -33,7 +35,7 @@
         features = ['cxx', 'cprogram'],
         source   = common_sources + egl_sources,
         target   = 'glcompbench-egl-gl',
-        uselib   = ['egl', 'gl', 'x11', 'xdamage', 'xcomposite'],
+        uselib   = ['egl', 'gl'] + common_libs,
         use      = ['matrix'],
         lib      = ['m'],
         defines  = ['USE_EGL', 'USE_GL']
@@ -44,7 +46,7 @@
         features = ['cxx', 'cprogram'],
         source   = common_sources + egl_sources,
         target   = 'glcompbench-egl-es2',
-        uselib   = ['egl', 'glesv2', 'x11', 'xdamage', 'xcomposite'],
+        uselib   = ['egl', 'glesv2'] + common_libs,
         use      = ['matrix-es2'],
         lib      = ['m'],
         defines  = ['USE_EGL', 'USE_GLES2']
@@ -55,7 +57,7 @@
         features = ['cxx', 'cprogram'],
         source   = common_sources + glx_sources,
         target   = 'glcompbench-glx',
-        uselib   = ['gl', 'x11', 'xdamage', 'xcomposite'],
+        uselib   = ['gl'] + common_libs,
         use      = ['matrix'],
         lib      = ['m'],
         defines  = ['USE_GLX', 'USE_GL']

=== modified file 'wscript'
--- wscript	2011-06-28 08:38:53 +0000
+++ wscript	2011-07-18 15:00:13 +0000
@@ -61,7 +61,9 @@
         ctx.check_cxx(function_name = func, header_name = header, uselib = uselib, mandatory = True)
 
     # Check required packages
-    req_pkgs = [('x11', 'x11'), ('xdamage', 'xdamage'), ('xcomposite', 'xcomposite')]
+    req_pkgs = [('x11', 'x11'), ('xdamage', 'xdamage'),
+                ('xcomposite', 'xcomposite'), ('pixman-1', 'pixman'),
+                ('xext', 'xext')]
     for (pkg, uselib) in req_pkgs:
         ctx.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs',
                 mandatory = True)

