=== modified file 'src/android.cpp'
--- src/android.cpp	2012-02-13 09:53:57 +0000
+++ src/android.cpp	2012-02-13 10:45:41 +0000
@@ -30,9 +30,26 @@
 #include "log.h"
 #include "util.h"
 #include "default-benchmarks.h"
+#include "main-loop.h"
 
 static Canvas *g_canvas;
 static std::vector<Benchmark *> g_benchmarks;
+static MainLoop *g_loop;
+
+class MainLoopAndroid : public MainLoop
+{
+public:
+    MainLoopAndroid(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
+        MainLoop(canvas, benchmarks) {}
+
+    virtual void after_scene_setup() {}
+
+    virtual void before_scene_teardown()
+    {
+        Log::info("%s FPS: %u", scene_->info_string().c_str(),
+                                scene_->average_fps());
+    }
+};
 
 static void
 add_default_benchmarks(std::vector<Benchmark *> &benchmarks)
@@ -53,6 +70,7 @@
 {
     static_cast<void>(clazz);
 
+    Options::reuse_context = true;
     Log::init("glmark2", false);
     Util::android_set_asset_manager(AAssetManager_fromJava(env, asset_manager));
 
@@ -76,6 +94,7 @@
     Benchmark::register_scene(*new SceneBuffer(*g_canvas));
 
     add_default_benchmarks(g_benchmarks);
+    g_loop = new MainLoopAndroid(*g_canvas, g_benchmarks);
 }
 
 void
@@ -96,6 +115,7 @@
 {
     static_cast<void>(env);
 
+    delete g_loop;
     delete g_canvas;
 }
 
@@ -103,50 +123,10 @@
 Java_org_linaro_glmark2_Glmark2Renderer_nativeRender(JNIEnv* env)
 {
     static_cast<void>(env);
-    static std::vector<Benchmark *>::iterator bench_iter = g_benchmarks.begin();
-    static Scene *scene = 0;
-    static unsigned int score = 0;
-    static unsigned int benchmarks_run = 0;
-
-    if (!scene) {
-        /* Find the next normal scene */
-        while (bench_iter != g_benchmarks.end()) {
-            scene = &(*bench_iter)->setup_scene();
-            if (!scene->name().empty())
-                break;
-            bench_iter++;
-        }
-
-        if (bench_iter == g_benchmarks.end()) {
-            if (benchmarks_run)
-                score /= benchmarks_run;
-            Log::info("glmark2 Score: %u\n", score);
-            /* Reset the rendering state, in case we get called again */
-            bench_iter = g_benchmarks.begin();
-            score = 0;
-            benchmarks_run = 0;
-            return false;
-        }
-    }
-
-    if (scene->is_running()) {
-        g_canvas->clear();
-
-        scene->draw();
-        scene->update();
-    }
-
-    /* 
-     * Need to recheck whether screen is running, because scene->update()
-     * may have changed the state.
-     */
-    if (!scene->is_running()) {
-        Log::info("%s FPS: %u", scene->info_string().c_str(), scene->average_fps());
-        score += scene->average_fps();
-        (*bench_iter)->teardown_scene();
-        scene = 0;
-        bench_iter++;
-        benchmarks_run++;
+
+    if (!g_loop->step()) {
+        Log::info("glmark2 Score: %u\n", g_loop->score());
+        return false;
     }
 
     return true;

=== added file 'src/main-loop.cpp'
--- src/main-loop.cpp	1970-01-01 00:00:00 +0000
+++ src/main-loop.cpp	2012-02-13 10:44:42 +0000
@@ -0,0 +1,236 @@
+/*
+ * Copyright © 2012 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 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.
+ *
+ * glmark2 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
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis
+ */
+#include "options.h"
+#include "main-loop.h"
+#include "util.h"
+#include "log.h"
+
+#include <string>
+#include <sstream>
+
+/************
+ * MainLoop *
+ ************/
+
+MainLoop::MainLoop(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
+    canvas_(canvas), benchmarks_(benchmarks)
+{
+    reset();
+}
+
+void
+MainLoop::reset()
+{
+    scene_ = 0;
+    score_ = 0;
+    benchmarks_run_ = 0;
+    bench_iter_ = benchmarks_.begin();
+}
+
+unsigned int
+MainLoop::score()
+{
+    if (benchmarks_run_)
+        return score_ / benchmarks_run_;
+    else
+        return score_;
+}
+
+bool
+MainLoop::step()
+{
+    /* Find the next normal scene */
+    if (!scene_) {
+        /* Find a normal scene */
+        while (bench_iter_ != benchmarks_.end()) {
+            scene_ = &(*bench_iter_)->scene();
+
+            /* 
+             * Scenes with empty names are option-setting scenes.
+             * Just set them up and continue with the search.
+             */
+            if (scene_->name().empty())
+                (*bench_iter_)->setup_scene();
+            else
+                break;
+
+            bench_iter_++;
+        }
+
+        /* If we have found a valid scene, set it up */
+        if (bench_iter_ != benchmarks_.end()) {
+            if (!Options::reuse_context)
+                canvas_.reset();
+            before_scene_setup();
+            scene_ = &(*bench_iter_)->setup_scene();
+            after_scene_setup();
+        }
+        else {
+            /* ... otherwise we are done */
+            return false;
+        }
+    }
+
+    bool should_quit = canvas_.should_quit();
+
+    if (scene_ ->running() && !should_quit)
+        draw();
+
+    /*
+     * Need to recheck whether the scene is still running, because code
+     * in draw() may have changed the state.
+     */
+    if (!scene_->running() || should_quit) {
+        score_ += scene_->average_fps();
+        before_scene_teardown();
+        (*bench_iter_)->teardown_scene();
+        scene_ = 0;
+        bench_iter_++;
+        benchmarks_run_++;
+    }
+
+    return !should_quit;
+}
+
+void
+MainLoop::draw()
+{
+    canvas_.clear();
+
+    scene_->draw();
+    scene_->update();
+
+    canvas_.update();
+}
+
+void
+MainLoop::after_scene_setup()
+{
+    Log::info("%s", scene_->info_string().c_str());
+    Log::flush();
+}
+
+void
+MainLoop::before_scene_teardown()
+{
+    static const std::string format(Log::continuation_prefix + " FPS: %u\n");
+    Log::info(format.c_str(), scene_->average_fps());
+}
+
+/**********************
+ * MainLoopDecoration *
+ **********************/
+
+MainLoopDecoration::MainLoopDecoration(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
+    MainLoop(canvas, benchmarks), fps_renderer_(0), last_fps_(0)
+{
+
+}
+
+MainLoopDecoration::~MainLoopDecoration()
+{
+    delete fps_renderer_;
+    fps_renderer_ = 0;
+}
+
+void
+MainLoopDecoration::draw()
+{
+    static const unsigned int fps_interval = 500000;
+    uint64_t now = Util::get_timestamp_us();
+
+    canvas_.clear();
+
+    scene_->draw();
+    scene_->update();
+
+    if (now - fps_timestamp_ >= fps_interval) {
+        last_fps_ = scene_->average_fps();
+        fps_renderer_update_text(last_fps_);
+        fps_timestamp_ = now;
+    }
+    fps_renderer_->render();
+
+    canvas_.update();
+}
+
+void
+MainLoopDecoration::before_scene_setup()
+{
+    delete fps_renderer_;
+    fps_renderer_ = new TextRenderer(canvas_);
+    fps_renderer_update_text(last_fps_);
+    fps_timestamp_ = Util::get_timestamp_us();
+}
+
+void
+MainLoopDecoration::fps_renderer_update_text(unsigned int fps)
+{
+    std::stringstream ss;
+    ss << "FPS: " << fps;
+    fps_renderer_->text(ss.str());
+}
+
+/**********************
+ * MainLoopValidation *
+ **********************/
+
+MainLoopValidation::MainLoopValidation(Canvas &canvas, const std::vector<Benchmark *> &benchmarks) :
+        MainLoop(canvas, benchmarks)
+{
+}
+
+void
+MainLoopValidation::draw()
+{
+    /* Draw only the first frame of the scene and stop */
+    canvas_.clear();
+
+    scene_->draw();
+
+    canvas_.update();
+
+    scene_->running(false);
+}
+
+void
+MainLoopValidation::before_scene_teardown()
+{
+    static const std::string format(Log::continuation_prefix + " Validation: %s\n");
+    std::string result;
+
+    switch(scene_->validate()) {
+        case Scene::ValidationSuccess:
+            result = "Success";
+            break;
+        case Scene::ValidationFailure:
+            result = "Failure";
+            break;
+        case Scene::ValidationUnknown:
+            result = "Unknown";
+            break;
+        default:
+            break;
+    }
+
+    Log::info(format.c_str(), result.c_str());
+}

=== added file 'src/main-loop.h'
--- src/main-loop.h	1970-01-01 00:00:00 +0000
+++ src/main-loop.h	2012-02-13 10:44:42 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright © 2012 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 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.
+ *
+ * glmark2 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
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis
+ */
+#ifndef GLMARK2_MAIN_LOOP_H_
+#define GLMARK2_MAIN_LOOP_H_
+
+#include "canvas.h"
+#include "benchmark.h"
+#include "text-renderer.h"
+#include <vector>
+
+/**
+ * Main loop for benchmarking.
+ */
+class MainLoop
+{
+public:
+    MainLoop(Canvas &canvas, const std::vector<Benchmark *> &benchmarks);
+
+    virtual ~MainLoop() {}
+
+    /**
+     * Resets the main loop.
+     *
+     * You need to call reset() if the loop has finished and
+     * you need to run it again.
+     */
+    void reset();
+
+    /**
+     * Gets the current total benchmarking score.
+     */
+    unsigned int score();
+
+    /**
+     * Perform the next main loop step.
+     *
+     * @returns whether the loop has finished
+     */
+    bool step();
+
+    /**
+     * Overridable method for drawing the canvas contents.
+     */
+    virtual void draw();
+
+    /**
+     * Overridable method for pre scene-setup customizations.
+     */
+    virtual void before_scene_setup() {}
+
+    /**
+     * Overridable method for post scene-setup customizations.
+     */
+    virtual void after_scene_setup();
+
+    /**
+     * Overridable method for pre scene-teardown customizations.
+     */
+    virtual void before_scene_teardown();
+
+protected:
+    Canvas &canvas_;
+    Scene *scene_;
+    const std::vector<Benchmark *> &benchmarks_;
+    unsigned int score_;
+    unsigned int benchmarks_run_;
+
+    std::vector<Benchmark *>::const_iterator bench_iter_;
+};
+
+/**
+ * Main loop for benchmarking with decorations (eg FPS, demo)
+ */
+class MainLoopDecoration : public MainLoop
+{
+public:
+    MainLoopDecoration(Canvas &canvas, const std::vector<Benchmark *> &benchmarks);
+    virtual ~MainLoopDecoration();
+
+    virtual void draw();
+    virtual void before_scene_setup();
+
+protected:
+    void fps_renderer_update_text(unsigned int fps);
+    TextRenderer *fps_renderer_;
+    unsigned int last_fps_;
+    uint64_t fps_timestamp_;
+};
+
+/**
+ * Main loop for validation.
+ */
+class MainLoopValidation : public MainLoop
+{
+public:
+    MainLoopValidation(Canvas &canvas, const std::vector<Benchmark *> &benchmarks);
+
+    virtual void draw();
+    virtual void before_scene_teardown();
+};
+
+#endif /* GLMARK2_MAIN_LOOP_H_ */

=== modified file 'src/main.cpp'
--- src/main.cpp	2012-01-27 22:01:59 +0000
+++ src/main.cpp	2012-02-13 10:45:33 +0000
@@ -30,6 +30,7 @@
 #include "util.h"
 #include "default-benchmarks.h"
 #include "text-renderer.h"
+#include "main-loop.h"
 
 #include <iostream>
 #include <fstream>
@@ -174,115 +175,24 @@
 void
 do_benchmark(Canvas &canvas, vector<Benchmark *> &benchmarks)
 {
-    static const unsigned int fps_interval = 500000;
-    unsigned score = 0;
-    unsigned int last_fps = 0;
-    unsigned int benchmarks_run = 0;
-    static const string format(Log::continuation_prefix + " FPS: %u\n");
-
-    for (vector<Benchmark *>::iterator bench_iter = benchmarks.begin();
-         bench_iter != benchmarks.end();
-         bench_iter++)
-    {
-        if (!Options::reuse_context)
-            canvas.reset();
-
-        TextRenderer fps_renderer(canvas);
-        if (Options::show_fps)
-            fps_renderer_update_text(fps_renderer, last_fps);
-
-        bool keep_running = true;
-        Benchmark *bench = *bench_iter;
-        uint64_t fps_timestamp = Util::get_timestamp_us();
-        Scene &scene = bench->setup_scene();
-
-        if (!scene.name().empty()) {
-            Log::info("%s", scene.info_string().c_str());
-            Log::flush();
-
-            while (scene.is_running() &&
-                   (keep_running = !canvas.should_quit()))
-            {
-                canvas.clear();
-
-                scene.draw();
-                scene.update();
-
-                if (Options::show_fps) {
-                    uint64_t now = Util::get_timestamp_us();
-                    if (now - fps_timestamp >= fps_interval) {
-                        last_fps = scene.average_fps();
-                        fps_renderer_update_text(fps_renderer, last_fps);
-                        fps_timestamp = now;
-                    }
-                    fps_renderer.render();
-                }
-
-                canvas.update();
-            }
-
-            Log::info(format.c_str(), scene.average_fps());
-            score += scene.average_fps();
-            benchmarks_run++;
-        }
-
-        bench->teardown_scene();
-
-        if (!keep_running)
-            break;
-    }
-
-    if (benchmarks_run)
-        score /= benchmarks_run;
-
-    Log::info("=======================================================\n");
-    Log::info("                                  glmark2 Score: %u \n", score);
-    Log::info("=======================================================\n");
-
+    MainLoop loop_normal(canvas, benchmarks);
+    MainLoopDecoration loop_decoration(canvas, benchmarks);
+
+    MainLoop &loop(Options::show_fps ? loop_decoration : loop_normal);
+    
+    while (loop.step());
+
+    Log::info("=======================================================\n");
+    Log::info("                                  glmark2 Score: %u \n", loop.score());
+    Log::info("=======================================================\n");
 }
 
 void
 do_validation(Canvas &canvas, vector<Benchmark *> &benchmarks)
 {
-    static const string format(Log::continuation_prefix + " Validation: %s\n");
-    for (vector<Benchmark *>::iterator bench_iter = benchmarks.begin();
-         bench_iter != benchmarks.end();
-         bench_iter++)
-    {
-        if (!Options::reuse_context)
-            canvas.reset();
-
-        Benchmark *bench = *bench_iter;
-        Scene &scene = bench->setup_scene();
-
-        if (!scene.name().empty()) {
-            Log::info("%s", scene.info_string().c_str());
-            Log::flush();
-
-            canvas.clear();
-            scene.draw();
-            canvas.update();
-
-            string result;
-            switch(scene.validate()) {
-                case Scene::ValidationSuccess:
-                    result = "Success";
-                    break;
-                case Scene::ValidationFailure:
-                    result = "Failure";
-                    break;
-                case Scene::ValidationUnknown:
-                    result = "Unknown";
-                    break;
-                default:
-                    break;
-            }
-
-            Log::info(format.c_str(), result.c_str());
-        }
-
-        bench->teardown_scene();
-    }
+    MainLoopValidation loop(canvas, benchmarks);
+
+    while (loop.step());
 }
 
 int

=== modified file 'src/scene.cpp'
--- src/scene.cpp	2011-12-08 13:19:41 +0000
+++ src/scene.cpp	2012-02-09 01:28:16 +0000
@@ -121,13 +121,6 @@
     return currentFrame_ / elapsed_time;
 }
 
-
-bool
-Scene::is_running()
-{
-    return running_;
-}
-
 bool
 Scene::set_option(const string &opt, const string &val)
 {

=== modified file 'src/scene.h'
--- src/scene.h	2011-12-08 13:19:41 +0000
+++ src/scene.h	2012-02-09 01:28:16 +0000
@@ -146,7 +146,14 @@
      *
      * @return true if running, false otherwise
      */
-    bool is_running();
+    bool running() { return running_; }
+
+    /**
+     * Sets whether this scene is running.
+     *
+     * @return true if running, false otherwise
+     */
+    void running(bool r) { running_ = r; }
 
     /**
      * Gets the average FPS value for this scene.

