Support using OpenGL ES context on desktop

Support using OpenGL ES context on desktop for unix and Android platforms. This
is mainly useful in development.

Add --gpuAPI flag to gm, dm, bench, bench_pictures and render_pictures. The
possible parameters for the flag are "gl" and "gles".

R=bsalomon@google.com, mtklein@google.com, robertphillips@google.com

Author: kkinnunen@nvidia.com

Review URL: https://codereview.chromium.org/319043005
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 64a4bc5..afe7573 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -37,8 +37,15 @@
 using skiatest::Test;
 using skiatest::TestRegistry;
 
+static const char kGpuAPINameGL[] = "gl";
+static const char kGpuAPINameGLES[] = "gles";
+
 DEFINE_int32(threads, -1, "Threads for CPU work. Default NUM_CPUS.");
 DEFINE_int32(gpuThreads, 1, "Threads for GPU work.");
+DEFINE_string(gpuAPI, "", "Force use of specific gpu API.  Using \"gl\" "
+              "forces OpenGL API. Using \"gles\" forces OpenGL ES API. "
+              "Defaults to empty string, which selects the API native to the "
+              "system.");
 DEFINE_string2(expectations, r, "",
                "If a directory, compare generated images against images under this path. "
                "If a file, compare generated images against JSON expectations at this path."
@@ -95,6 +102,7 @@
 
 static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms,
                          const SkTArray<SkString>& configs,
+                         GrGLStandard gpuAPI,
                          const DM::Expectations& expectations,
                          DM::Reporter* reporter,
                          DM::TaskRunner* tasks) {
@@ -104,17 +112,18 @@
     }
     for (int i = 0; i < gms.count(); i++) {
         for (int j = 0; j < configs.count(); j++) {
+
             START("565",        CpuGMTask, expectations, kRGB_565_SkColorType);
             START("8888",       CpuGMTask, expectations, kN32_SkColorType);
-            START("gpu",        GpuGMTask, expectations, native, 0);
-            START("msaa4",      GpuGMTask, expectations, native, 4);
-            START("msaa16",     GpuGMTask, expectations, native, 16);
-            START("nvprmsaa4",  GpuGMTask, expectations, nvpr,   4);
-            START("nvprmsaa16", GpuGMTask, expectations, nvpr,   16);
-            START("gpunull",    GpuGMTask, expectations, null,   0);
-            START("gpudebug",   GpuGMTask, expectations, debug,  0);
-            START("angle",      GpuGMTask, expectations, angle,  0);
-            START("mesa",       GpuGMTask, expectations, mesa,   0);
+            START("gpu",        GpuGMTask, expectations, native, gpuAPI, 0);
+            START("msaa4",      GpuGMTask, expectations, native, gpuAPI, 4);
+            START("msaa16",     GpuGMTask, expectations, native, gpuAPI, 16);
+            START("nvprmsaa4",  GpuGMTask, expectations, nvpr,   gpuAPI, 4);
+            START("nvprmsaa16", GpuGMTask, expectations, nvpr,   gpuAPI, 16);
+            START("gpunull",    GpuGMTask, expectations, null,   gpuAPI, 0);
+            START("gpudebug",   GpuGMTask, expectations, debug,  gpuAPI, 0);
+            START("angle",      GpuGMTask, expectations, angle,  gpuAPI, 0);
+            START("mesa",       GpuGMTask, expectations, mesa,   gpuAPI, 0);
             START("pdf",        PDFTask,   RASTERIZE_PDF_PROC);
         }
     }
@@ -123,6 +132,7 @@
 
 static void kick_off_benches(const SkTDArray<BenchRegistry::Factory>& benches,
                              const SkTArray<SkString>& configs,
+                             GrGLStandard gpuAPI,
                              DM::Reporter* reporter,
                              DM::TaskRunner* tasks) {
 #define START(name, type, ...)                                                                 \
@@ -134,15 +144,15 @@
             START("nonrendering", NonRenderingBenchTask);
             START("565",          CpuBenchTask, kRGB_565_SkColorType);
             START("8888",         CpuBenchTask, kN32_SkColorType);
-            START("gpu",          GpuBenchTask, native, 0);
-            START("msaa4",        GpuBenchTask, native, 4);
-            START("msaa16",       GpuBenchTask, native, 16);
-            START("nvprmsaa4",    GpuBenchTask, nvpr,   4);
-            START("nvprmsaa16",   GpuBenchTask, nvpr,   16);
-            START("gpunull",      GpuBenchTask, null,   0);
-            START("gpudebug",     GpuBenchTask, debug,  0);
-            START("angle",        GpuBenchTask, angle,  0);
-            START("mesa",         GpuBenchTask, mesa,   0);
+            START("gpu",          GpuBenchTask, native, gpuAPI, 0);
+            START("msaa4",        GpuBenchTask, native, gpuAPI, 4);
+            START("msaa16",       GpuBenchTask, native, gpuAPI, 16);
+            START("nvprmsaa4",    GpuBenchTask, nvpr,   gpuAPI, 4);
+            START("nvprmsaa16",   GpuBenchTask, nvpr,   gpuAPI, 16);
+            START("gpunull",      GpuBenchTask, null,   gpuAPI, 0);
+            START("gpudebug",     GpuBenchTask, debug,  gpuAPI, 0);
+            START("angle",        GpuBenchTask, angle,  gpuAPI, 0);
+            START("mesa",         GpuBenchTask, mesa,   gpuAPI, 0);
         }
     }
 #undef START
@@ -204,6 +214,16 @@
     SkDebugf("%d failures.\n", failures.count());
 }
 
+static GrGLStandard get_gl_standard() {
+  if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) {
+      return kGL_GrGLStandard;
+  }
+  if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) {
+      return kGLES_GrGLStandard;
+  }
+  return kNone_GrGLStandard;
+}
+
 template <typename T, typename Registry>
 static void append_matching_factories(Registry* head, SkTDArray<typename Registry::Factory>* out) {
     for (const Registry* reg = head; reg != NULL; reg = reg->next()) {
@@ -232,6 +252,8 @@
         SkStrSplit(FLAGS_config[i], ", ", &configs);
     }
 
+    GrGLStandard gpuAPI = get_gl_standard();
+
     SkTDArray<GMRegistry::Factory> gms;
     SkAutoTDelete<DM::Expectations> expectations(SkNEW(DM::NoExpectations));
     if (FLAGS_gms) {
@@ -261,8 +283,8 @@
              gms.count(), benches.count(), configs.count(), tests.count());
     DM::Reporter reporter;
     DM::TaskRunner tasks(FLAGS_threads, FLAGS_gpuThreads);
-    kick_off_gms(gms, configs, *expectations, &reporter, &tasks);
-    kick_off_benches(benches, configs, &reporter, &tasks);
+    kick_off_gms(gms, configs, gpuAPI, *expectations, &reporter, &tasks);
+    kick_off_benches(benches, configs, gpuAPI, &reporter, &tasks);
     kick_off_tests(tests, &reporter, &tasks);
     kick_off_skps(&reporter, &tasks);
     tasks.wait();
diff --git a/dm/DMBenchTask.cpp b/dm/DMBenchTask.cpp
index 7cd2fdc..9bdbbf2 100644
--- a/dm/DMBenchTask.cpp
+++ b/dm/DMBenchTask.cpp
@@ -33,11 +33,13 @@
                            TaskRunner* tasks,
                            BenchRegistry::Factory factory,
                            GrContextFactory::GLContextType contextType,
+                           GrGLStandard gpuAPI,
                            int sampleCount)
     : GpuTask(reporter, tasks)
     , fBench(factory(NULL))
     , fName(bench_name(fBench->getName(), config))
     , fContextType(contextType)
+    , fGpuAPI(gpuAPI)
     , fSampleCount(sampleCount) {}
 
 bool NonRenderingBenchTask::shouldSkip() const {
@@ -74,8 +76,12 @@
                                          fBench->getSize().y(),
                                          kN32_SkColorType,
                                          kPremul_SkAlphaType);
-    SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, info, fSampleCount));
-
+    SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, fGpuAPI, info,
+                                                  fSampleCount));
+    if (!surface) {
+        this->fail("Could not create context for the config and the api.");
+        return;
+    }
     fBench->preDraw();
     fBench->draw(1, surface->getCanvas());
 }
diff --git a/dm/DMBenchTask.h b/dm/DMBenchTask.h
index 3c71cd7..d2b5800 100644
--- a/dm/DMBenchTask.h
+++ b/dm/DMBenchTask.h
@@ -46,6 +46,7 @@
                  TaskRunner*,
                  BenchRegistry::Factory,
                  GrContextFactory::GLContextType,
+                 GrGLStandard gpuAPI,
                  int sampleCount);
 
     virtual void draw(GrContextFactory*) SK_OVERRIDE;
@@ -56,6 +57,7 @@
     SkAutoTDelete<Benchmark> fBench;
     const SkString fName;
     const GrContextFactory::GLContextType fContextType;
+    const GrGLStandard fGpuAPI;
     int fSampleCount;
 };
 
diff --git a/dm/DMGpuGMTask.cpp b/dm/DMGpuGMTask.cpp
index b384485..4c44fae 100644
--- a/dm/DMGpuGMTask.cpp
+++ b/dm/DMGpuGMTask.cpp
@@ -15,12 +15,14 @@
                      skiagm::GMRegistry::Factory gmFactory,
                      const Expectations& expectations,
                      GrContextFactory::GLContextType contextType,
+                     GrGLStandard gpuAPI,
                      int sampleCount)
     : GpuTask(reporter, taskRunner)
     , fGM(gmFactory(NULL))
     , fName(UnderJoin(fGM->getName(), config))
     , fExpectations(expectations)
     , fContextType(contextType)
+    , fGpuAPI(gpuAPI)
     , fSampleCount(sampleCount)
     {}
 
@@ -29,7 +31,12 @@
                                          SkScalarCeilToInt(fGM->height()),
                                          kN32_SkColorType,
                                          kPremul_SkAlphaType);
-    SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, info, fSampleCount));
+    SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, fGpuAPI, info,
+                                                  fSampleCount));
+    if (!surface) {
+        this->fail("Could not create context for the config and the api.");
+        return;
+    }
     SkCanvas* canvas = surface->getCanvas();
 
     canvas->concat(fGM->getInitialTransform());
diff --git a/dm/DMGpuGMTask.h b/dm/DMGpuGMTask.h
index 6621a49..46b4c98 100644
--- a/dm/DMGpuGMTask.h
+++ b/dm/DMGpuGMTask.h
@@ -23,6 +23,7 @@
               skiagm::GMRegistry::Factory,
               const Expectations&,
               GrContextFactory::GLContextType,
+              GrGLStandard gpuAPI,
               int sampleCount);
 
     virtual void draw(GrContextFactory*) SK_OVERRIDE;
@@ -34,6 +35,7 @@
     const SkString fName;
     const Expectations& fExpectations;
     const GrContextFactory::GLContextType fContextType;
+    GrGLStandard fGpuAPI;
     const int fSampleCount;
 };
 
diff --git a/dm/DMGpuSupport.h b/dm/DMGpuSupport.h
index 46896b4..bcc00c2 100644
--- a/dm/DMGpuSupport.h
+++ b/dm/DMGpuSupport.h
@@ -19,9 +19,10 @@
 
 static inline SkSurface* NewGpuSurface(GrContextFactory* grFactory,
                                        GrContextFactory::GLContextType type,
+                                       GrGLStandard gpuAPI,
                                        SkImageInfo info,
                                        int samples) {
-    return SkSurface::NewRenderTarget(grFactory->get(type), info, samples);
+    return SkSurface::NewRenderTarget(grFactory->get(type, gpuAPI), info, samples);
 }
 
 }  // namespace DM
@@ -30,6 +31,12 @@
 
 // Ganesh is not available.  Fake it.
 
+enum GrGLStandard {
+    kNone_GrGLStandard,
+    kGL_GrGLStandard,
+    kGLES_GrGLStandard
+};
+
 class GrContextFactory {
 public:
     typedef int GLContextType;
@@ -48,6 +55,7 @@
 
 static inline SkSurface* NewGpuSurface(GrContextFactory*,
                                        GrContextFactory::GLContextType,
+                                       GrGLStandard,
                                        SkImageInfo,
                                        int) {
     return NULL;