Added gflags switches: duration, tests, save, out.
Added saving images after a testcase is finished.
Updated power_Draw control file.

Checking against golden images will be done outside from a python script.

Review URL: http://codereview.chromium.org/2794002
diff --git a/client/deps/glbench/src/attributefetchtest.cc b/client/deps/glbench/src/attributefetchtest.cc
index 2cc25ce..910bbc6 100644
--- a/client/deps/glbench/src/attributefetchtest.cc
+++ b/client/deps/glbench/src/attributefetchtest.cc
@@ -14,6 +14,7 @@
   AttributeFetchShaderTest() {}
   virtual ~AttributeFetchShaderTest() {}
   virtual bool Run();
+  virtual const char* Name() const { return "attribute_fetch_shader"; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AttributeFetchShaderTest);
diff --git a/client/deps/glbench/src/cleartest.cc b/client/deps/glbench/src/cleartest.cc
index 8ef0491..8daf3ea 100644
--- a/client/deps/glbench/src/cleartest.cc
+++ b/client/deps/glbench/src/cleartest.cc
@@ -15,6 +15,7 @@
   virtual ~ClearTest() {}
   virtual bool TestFunc(int iter);
   virtual bool Run();
+  virtual const char* Name() const { return "clear"; }
 
  private:
   GLbitfield mask_;
diff --git a/client/deps/glbench/src/fillratetest.cc b/client/deps/glbench/src/fillratetest.cc
index 1378e16..426a3a4 100644
--- a/client/deps/glbench/src/fillratetest.cc
+++ b/client/deps/glbench/src/fillratetest.cc
@@ -15,6 +15,7 @@
   FillRateTest() {}
   virtual ~FillRateTest() {}
   virtual bool Run();
+  virtual const char* Name() const { return "fill_rate"; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(FillRateTest);
diff --git a/client/deps/glbench/src/main.cc b/client/deps/glbench/src/main.cc
index d112658..d777481 100644
--- a/client/deps/glbench/src/main.cc
+++ b/client/deps/glbench/src/main.cc
@@ -2,60 +2,55 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fcntl.h>
+#include <gflags/gflags.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
 
 #include "base/logging.h"
+#include "base/string_util.h"
 
 #include "main.h"
 #include "utils.h"
-#include "yuv2rgb.h"
 
 #include "all_tests.h"
 #include "testbase.h"
 
+using std::string;
+using std::vector;
 
-const int enabled_tests_max = 8;
-// TODO: fix enabled_tests.
-const char *enabled_tests[enabled_tests_max+1] = {NULL};
-int seconds_to_run = 0;
+DEFINE_int32(duration, 0, "run tests in a loop for at least this many seconds");
+DEFINE_string(tests, "", "colon-separated list of tests to run; "
+              "all tests if omitted");
 
 
-// TODO: use proper command line parsing library.
-static void ParseArgs(int argc, char *argv[]) {
-  const char **enabled_tests_ptr = enabled_tests;
-  bool test_name_arg = false;
-  bool duration_arg = false;
-  for (int i = 0; i < argc; i++) {
-    if (test_name_arg) {
-      test_name_arg = false;
-      *enabled_tests_ptr++ = argv[i];
-      if (enabled_tests_ptr - enabled_tests >= enabled_tests_max)
-        break;
-    } else if (duration_arg) {
-      duration_arg = false;
-      seconds_to_run = atoi(argv[i]);
-    } else if (strcmp("-t", argv[i]) == 0) {
-      test_name_arg = true;
-    } else if (strcmp("-d", argv[i]) == 0) {
-      duration_arg = true;
-    }
+bool test_is_enabled(glbench::TestBase* test,
+                     const vector<string>& enabled_tests) {
+  if (enabled_tests.empty())
+    return true;
+
+  const char* test_name = test->Name();
+  for (vector<string>::const_iterator i = enabled_tests.begin();
+       i != enabled_tests.end(); ++i) {
+    // This is not very precise, but will do until there's a need for something
+    // more flexible.
+    if (strstr(test_name, i->c_str()))
+      return true;
   }
-  *enabled_tests_ptr++ = NULL;
-}
 
+  return false;
+}
 
 int main(int argc, char *argv[]) {
   SetBasePathFromArgv0(argv[0], "src");
-  ParseArgs(argc, argv);
+  google::ParseCommandLineFlags(&argc, &argv, true);
   if (!Init()) {
     printf("# Failed to initialize.\n");
     return 1;
   }
 
+  vector<string> enabled_tests;
+  SplitString(FLAGS_tests, ':', &enabled_tests);
+
   glbench::TestBase* tests[] = {
     glbench::GetSwapTest(),
     glbench::GetClearTest(),
@@ -72,10 +67,18 @@
     glbench::GetTextureUpdateTest(),
   };
 
+  uint64_t done = GetUTime() + 1000000ULL * FLAGS_duration;
+  do {
+    for (unsigned int i = 0; i < arraysize(tests); i++) {
+      if (!test_is_enabled(tests[i], enabled_tests))
+        continue;
+      InitContext();
+      tests[i]->Run();
+      DestroyContext();
+    }
+  } while (GetUTime() < done);
+
   for (unsigned int i = 0; i < arraysize(tests); i++) {
-    InitContext();
-    tests[i]->Run();
-    DestroyContext();
     delete tests[i];
     tests[i] = NULL;
   }
diff --git a/client/deps/glbench/src/readpixeltest.cc b/client/deps/glbench/src/readpixeltest.cc
index 4d6d420..b5acdfa 100644
--- a/client/deps/glbench/src/readpixeltest.cc
+++ b/client/deps/glbench/src/readpixeltest.cc
@@ -18,6 +18,7 @@
   virtual ~ReadPixelTest() {}
   virtual bool TestFunc(int iter);
   virtual bool Run();
+  virtual const char* Name() const { return "pixel_read"; }
 
  private:
   void* pixels_;
diff --git a/client/deps/glbench/src/swaptest.cc b/client/deps/glbench/src/swaptest.cc
index f02acbe..2d724d4 100644
--- a/client/deps/glbench/src/swaptest.cc
+++ b/client/deps/glbench/src/swaptest.cc
@@ -15,6 +15,7 @@
   virtual ~SwapTest() {}
   virtual bool TestFunc(int iter);
   virtual bool Run();
+  virtual const char* Name() const { return "swap"; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SwapTest);
diff --git a/client/deps/glbench/src/testbase.cc b/client/deps/glbench/src/testbase.cc
index d200266..37af73f 100644
--- a/client/deps/glbench/src/testbase.cc
+++ b/client/deps/glbench/src/testbase.cc
@@ -2,9 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <gflags/gflags.h>
 #include <stdio.h>
 
+#include "base/scoped_ptr.h"
+#include "base/file_util.h"
+
 #include "testbase.h"
+#include "utils.h"
+
+DEFINE_bool(save, false, "save images after each test case");
+DEFINE_string(out, "out", "directory to save images");
 
 namespace glbench {
 
@@ -62,7 +70,18 @@
   return true;
 }
 
-void RunTest(TestBase* test, const char *name,
+void SaveImage(const char* name) {
+  const int size = g_width * g_height * 4;
+  scoped_array<char> pixels(new char[size]);
+  glReadPixels(0, 0, g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE,
+               pixels.get());
+  FilePath dirname = GetBasePath().Append(FLAGS_out);
+  file_util::CreateDirectory(dirname);
+  FilePath filename = dirname.Append(name);
+  file_util::WriteFile(filename, pixels.get(), size);
+}
+
+void RunTest(TestBase* test, const char* name,
              float coefficient, bool inverse) {
   float slope;
   int64_t bias;
@@ -74,6 +93,8 @@
     printf("%s: Nan\n", name);
   } else {
     if (Bench(test, &slope, &bias)) {
+      if (FLAGS_save)
+        SaveImage(name);
       printf("%s: %g\n", name, coefficient * (inverse ? 1.f / slope : slope));
     } else {
       printf("# %s is too slow, returning zero.\n", name);
diff --git a/client/deps/glbench/src/testbase.h b/client/deps/glbench/src/testbase.h
index 1a617b0..ce2a4f6 100644
--- a/client/deps/glbench/src/testbase.h
+++ b/client/deps/glbench/src/testbase.h
@@ -44,6 +44,7 @@
   virtual bool TestFunc(int n) = 0;
   // Main entry point into the test.
   virtual bool Run() = 0;
+  virtual const char* Name() const = 0;
 };
 
 // Helper class to time glDrawArrays.
diff --git a/client/deps/glbench/src/textureupdatetest.cc b/client/deps/glbench/src/textureupdatetest.cc
index c9c9e40..2bc676b 100644
--- a/client/deps/glbench/src/textureupdatetest.cc
+++ b/client/deps/glbench/src/textureupdatetest.cc
@@ -20,6 +20,7 @@
   virtual ~TextureUpdateTest() {}
   bool TestFunc(int iter);
   virtual bool Run();
+  virtual const char* Name() const { return "texture_update"; }
 
   enum UpdateFlavor {
     TEX_IMAGE,
@@ -122,7 +123,9 @@
 
 
   UpdateFlavor flavors[] = {TEX_IMAGE, TEX_SUBIMAGE};
-  const std::string flavor_names[] = {"teximage2d", "texsubimage2d"};
+  const std::string flavor_names[] = {
+    "texture_update_teximage2d", "texture_update_texsubimage2d"
+  };
   for (unsigned int f = 0; f < arraysize(flavors); f++) {
     flavor_ = flavors[f];
     int sizes[] = {32, 128, 256, 512, 768, 1024, 1536, 2048};
diff --git a/client/deps/glbench/src/trianglesetuptest.cc b/client/deps/glbench/src/trianglesetuptest.cc
index 6610eed..e905b98 100644
--- a/client/deps/glbench/src/trianglesetuptest.cc
+++ b/client/deps/glbench/src/trianglesetuptest.cc
@@ -17,6 +17,7 @@
   TriangleSetupTest() {}
   virtual ~TriangleSetupTest() {}
   virtual bool Run();
+  virtual const char* Name() const { return "triangle_setup"; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TriangleSetupTest);
diff --git a/client/deps/glbench/src/utils.cc b/client/deps/glbench/src/utils.cc
index 8709faf..4dfc467 100644
--- a/client/deps/glbench/src/utils.cc
+++ b/client/deps/glbench/src/utils.cc
@@ -8,11 +8,9 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-#include "utils.h"
-
-#include "base/file_path.h"
 #include "base/logging.h"
 #include "main.h"
+#include "utils.h"
 
 FilePath *g_base_path = new FilePath();
 
@@ -26,6 +24,10 @@
   g_base_path = new FilePath(base_path);
 }
 
+const FilePath& GetBasePath() {
+  return *g_base_path;
+}
+
 void *MmapFile(const char* name, size_t* length) {
   FilePath filename = g_base_path->Append(name);
   int fd = open(filename.value().c_str(), O_RDONLY);
diff --git a/client/deps/glbench/src/utils.h b/client/deps/glbench/src/utils.h
index 434d081..34cf344 100644
--- a/client/deps/glbench/src/utils.h
+++ b/client/deps/glbench/src/utils.h
@@ -11,9 +11,11 @@
 #include "GL/gl.h"
 #endif
 
+#include "base/file_path.h"
 
 void SetBasePathFromArgv0(const char* argv0, const char* relative);
 void *MmapFile(const char *name, size_t *length);
+const FilePath& GetBasePath();
 
 namespace glbench {
 
diff --git a/client/deps/glbench/src/varyingsandddxytest.cc b/client/deps/glbench/src/varyingsandddxytest.cc
index 22ef1c3..7a0010f 100644
--- a/client/deps/glbench/src/varyingsandddxytest.cc
+++ b/client/deps/glbench/src/varyingsandddxytest.cc
@@ -15,6 +15,7 @@
   VaryingsAndDdxyShaderTest() {}
   virtual ~VaryingsAndDdxyShaderTest() {}
   virtual bool Run();
+  virtual const char* Name() const { return "varyings_ddx_shader"; }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(VaryingsAndDdxyShaderTest);
diff --git a/client/deps/glbench/src/windowmanagercompositingtest.cc b/client/deps/glbench/src/windowmanagercompositingtest.cc
index a791093..ee4426d 100644
--- a/client/deps/glbench/src/windowmanagercompositingtest.cc
+++ b/client/deps/glbench/src/windowmanagercompositingtest.cc
@@ -23,6 +23,7 @@
   virtual ~WindowManagerCompositingTest() {}
   virtual bool TestFunc(int iter);
   virtual bool Run();
+  virtual const char* Name() const { return "compositing"; }
 
   void InitializeCompositing();
   void TeardownCompositing();
diff --git a/client/deps/glbench/src/yuvtest.cc b/client/deps/glbench/src/yuvtest.cc
index 2ae23ab..34e1827 100644
--- a/client/deps/glbench/src/yuvtest.cc
+++ b/client/deps/glbench/src/yuvtest.cc
@@ -24,6 +24,7 @@
     glDeleteTextures(arraysize(textures_), textures_);
   }
   virtual bool Run();
+  virtual const char* Name() const { return "yuv_to_rgb"; }
 
   enum YuvTestFlavor {
     YUV_PLANAR_ONE_TEXTURE_SLOW,