support gpu for skottie2movie

-g will try to render the frames using OpenGL

For the motion-blur test skottie on Mac Pro...

Before: 71.0 secs
After :  6.6 secs

Change-Id: I7e723d4ac0bb63b0e42381ed50bf2144dfc9c8a3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243428
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/tools/skottie2movie.cpp b/tools/skottie2movie.cpp
index fa98b2a..48d5dee 100644
--- a/tools/skottie2movie.cpp
+++ b/tools/skottie2movie.cpp
@@ -14,7 +14,11 @@
 #include "modules/skottie/include/Skottie.h"
 #include "modules/skottie/utils/SkottieUtils.h"
 #include "src/utils/SkOSPath.h"
+
 #include "tools/flags/CommandLineFlags.h"
+#include "tools/gpu/GrContextFactory.h"
+
+#include "include/gpu/GrContextOptions.h"
 
 static DEFINE_string2(input, i, "", "skottie animation to render");
 static DEFINE_string2(output, o, "", "mp4 file to create");
@@ -23,6 +27,7 @@
 static DEFINE_bool2(verbose, v, false, "verbose mode");
 static DEFINE_bool2(loop, l, false, "loop mode for profiling");
 static DEFINE_int(set_dst_width, 0, "set destination width (height will be computed)");
+static DEFINE_bool2(gpu, g, false, "use GPU for rendering");
 
 static void produce_frame(SkSurface* surf, skottie::Animation* anim, double frame_time) {
     anim->seekFrameTime(frame_time);
@@ -30,6 +35,11 @@
     anim->render(surf->getCanvas());
 }
 
+struct AsyncRec {
+    SkImageInfo info;
+    SkVideoEncoder* encoder;
+};
+
 int main(int argc, char** argv) {
     SkGraphics::Init();
 
@@ -41,6 +51,10 @@
         return -1;
     }
 
+    auto contextType = sk_gpu_test::GrContextFactory::kGL_ContextType;
+    GrContextOptions grCtxOptions;
+    sk_gpu_test::GrContextFactory factory(grCtxOptions);
+
     SkString assetPath;
     if (FLAGS_assetPath.count() > 0) {
         assetPath.set(FLAGS_assetPath[0]);
@@ -82,20 +96,34 @@
 
     SkVideoEncoder encoder;
 
-    sk_sp<SkSurface> surf, tmp_surf;
+    GrContext* context = nullptr;
+    sk_sp<SkSurface> surf;
     sk_sp<SkData> data;
 
     do {
         double loop_start = SkTime::GetSecs();
 
         encoder.beginRecording(dim, fps);
+        auto info = encoder.preferredInfo();
+
         // lazily allocate the surfaces
         if (!surf) {
-            surf = SkSurface::MakeRaster(encoder.preferredInfo());
-            tmp_surf = surf->makeSurface(surf->width(), surf->height());
-
-                surf->getCanvas()->scale(scale, scale);
-            tmp_surf->getCanvas()->scale(scale, scale);
+            if (FLAGS_gpu) {
+                context = factory.getContextInfo(contextType).grContext();
+                surf = SkSurface::MakeRenderTarget(context,
+                                                   SkBudgeted::kNo,
+                                                   info,
+                                                   0,
+                                                   GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
+                                                   nullptr);
+                if (!surf) {
+                    context = nullptr;
+                }
+            }
+            if (!surf) {
+                surf = SkSurface::MakeRaster(info);
+            }
+            surf->getCanvas()->scale(scale, scale);
         }
 
         for (int i = 0; i <= frames; ++i) {
@@ -109,9 +137,19 @@
 
             produce_frame(surf.get(), animation.get(), frame_time);
 
-            SkPixmap pm;
-            SkAssertResult(surf->peekPixels(&pm));
-            encoder.addFrame(pm);
+            AsyncRec asyncRec = { info, &encoder };
+            if (context) {
+                surf->asyncRescaleAndReadPixels(info, {0, 0, info.width(), info.height()},
+                                                SkSurface::RescaleGamma::kSrc, kNone_SkFilterQuality,
+                                                [](void* ctx, const void* data, size_t rb) {
+                    AsyncRec* rec = (AsyncRec*)ctx;
+                    rec->encoder->addFrame({rec->info, data, rb});
+                }, &asyncRec);
+            } else {
+                SkPixmap pm;
+                SkAssertResult(surf->peekPixels(&pm));
+                encoder.addFrame(pm);
+            }
         }
         data = encoder.endRecording();