Add skiaBenchmarking.getOps()

Given a JSON-encoded Picture, the new function returns an array of Skia draw commands + info.

Depends on https://codereview.chromium.org/16638014/.

Re-landing after Skia SkDebugCanvas static initializer fix (https://code.google.com/p/skia/source/detail?r=9723).

[email protected], [email protected], [email protected]

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=207676

Review URL: https://codereview.chromium.org/15967010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208695 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/renderer/skia_benchmarking_extension.cc b/content/renderer/skia_benchmarking_extension.cc
index c916c39..0a1c608 100644
--- a/content/renderer/skia_benchmarking_extension.cc
+++ b/content/renderer/skia_benchmarking_extension.cc
@@ -12,6 +12,8 @@
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColorPriv.h"
 #include "third_party/skia/include/core/SkGraphics.h"
+#include "third_party/skia/src/utils/debugger/SkDebugCanvas.h"
+#include "third_party/skia/src/utils/debugger/SkDrawCommand.h"
 #include "ui/gfx/rect_conversions.h"
 #include "v8/include/v8.h"
 
@@ -21,6 +23,19 @@
 
 const char kSkiaBenchmarkingExtensionName[] = "v8/SkiaBenchmarking";
 
+static scoped_refptr<cc::Picture> ParsePictureArg(v8::Handle<v8::Value> arg) {
+  scoped_ptr<content::V8ValueConverter> converter(
+      content::V8ValueConverter::create());
+
+  v8::String::Value v8_picture(arg);
+  scoped_ptr<base::Value> picture_value(
+      converter->FromV8Value(arg, v8::Context::GetCurrent()));
+  if (!picture_value)
+    return NULL;
+
+  return cc::Picture::CreateFromValue(picture_value.get());
+}
+
 class SkiaBenchmarkingWrapper : public v8::Extension {
  public:
   SkiaBenchmarkingWrapper() :
@@ -39,10 +54,23 @@
         "     @param [Number, Number, Number, Number] clip_rect (optional)."
         "     @returns { 'width': {Number}, 'height': {Number},"
         "                'data': {ArrayBuffer} }"
+        "     @returns undefined if the arguments are invalid or the picture"
+        "                        version is not supported."
         "   */"
         "  native function Rasterize();"
         "  return Rasterize(picture, scale, rect);"
         "};"
+        "chrome.skiaBenchmarking.getOps = function(picture) {"
+        "  /* "
+        "     Extracts the Skia draw commands from a JSON-encoded cc::Picture"
+        "     @param {Object} picture A json-encoded cc::Picture."
+        "     @returns [{ 'cmd': {String}, 'info': [String, ...] }, ...]"
+        "     @returns undefined if the arguments are invalid or the picture"
+        "                        version is not supported."
+        "   */"
+        "  native function GetOps();"
+        "  return GetOps(picture);"
+        "};"
         ) {
       content::SkiaBenchmarkingExtension::InitSkGraphics();
   }
@@ -51,6 +79,8 @@
       v8::Handle<v8::String> name) OVERRIDE {
     if (name->Equals(v8::String::New("Rasterize")))
       return v8::FunctionTemplate::New(Rasterize);
+    if (name->Equals(v8::String::New("GetOps")))
+      return v8::FunctionTemplate::New(GetOps);
 
     return v8::Handle<v8::FunctionTemplate>();
   }
@@ -59,22 +89,7 @@
     if (args.Length() < 1)
       return;
 
-    WebFrame* web_frame = WebFrame::frameForCurrentContext();
-    if (!web_frame)
-      return;
-
-    scoped_ptr<content::V8ValueConverter> converter(
-        content::V8ValueConverter::create());
-
-    v8::String::Value v8_picture(args[0]);
-    scoped_ptr<base::Value> picture_value(
-        converter->FromV8Value(
-            args[0], v8::Context::GetCurrent()));
-    if (!picture_value)
-      return;
-
-    scoped_refptr<cc::Picture> picture =
-        cc::Picture::CreateFromValue(picture_value.get());
+    scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]);
     if (!picture.get())
       return;
 
@@ -140,6 +155,44 @@
 
     args.GetReturnValue().Set(result);
   }
+
+  static void GetOps(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    if (args.Length() != 1)
+      return;
+
+    scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]);
+    if (!picture.get())
+      return;
+
+    gfx::Rect bounds = picture->LayerRect();
+    SkDebugCanvas canvas(bounds.width(), bounds.height());
+    picture->Raster(&canvas, NULL, bounds, 1.0f);
+
+    v8::Local<v8::Array> result = v8::Array::New(canvas.getSize());
+    for (int i = 0; i < canvas.getSize(); ++i) {
+      DrawType cmd_type = canvas.getDrawCommandAt(i)->getType();
+      v8::Handle<v8::Object> cmd = v8::Object::New();
+      cmd->Set(v8::String::New("cmd_type"), v8::Integer::New(cmd_type));
+      cmd->Set(v8::String::New("cmd_string"), v8::String::New(
+          SkDrawCommand::GetCommandString(cmd_type)));
+
+      SkTDArray<SkString*>* info = canvas.getCommandInfo(i);
+      DCHECK(info);
+
+      v8::Local<v8::Array> v8_info = v8::Array::New(info->count());
+      for (int j = 0; j < info->count(); ++j) {
+        const SkString* info_str = (*info)[j];
+        DCHECK(info_str);
+        v8_info->Set(j, v8::String::New(info_str->c_str()));
+      }
+
+      cmd->Set(v8::String::New("info"), v8_info);
+
+      result->Set(i, cmd);
+    }
+
+    args.GetReturnValue().Set(result);
+  }
 };
 
 } // namespace