Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/skia_benchmarking_extension.h" | 5 #include "content/renderer/skia_benchmarking_extension.h" |
| 6 | 6 |
| 7 #include "base/values.h" | 7 #include "base/values.h" |
| 8 #include "cc/resources/picture.h" | 8 #include "cc/resources/picture.h" |
| 9 #include "content/public/renderer/v8_value_converter.h" | 9 #include "content/public/renderer/v8_value_converter.h" |
| 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" | 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebArrayBuffer.h" |
| 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 12 #include "third_party/skia/include/core/SkCanvas.h" | 12 #include "third_party/skia/include/core/SkCanvas.h" |
| 13 #include "third_party/skia/include/core/SkColorPriv.h" | 13 #include "third_party/skia/include/core/SkColorPriv.h" |
| 14 #include "third_party/skia/include/core/SkGraphics.h" | 14 #include "third_party/skia/include/core/SkGraphics.h" |
| 15 #include "third_party/skia/src/utils/debugger/SkDebugCanvas.h" | |
| 16 #include "third_party/skia/src/utils/debugger/SkDrawCommand.h" | |
| 15 #include "ui/gfx/rect_conversions.h" | 17 #include "ui/gfx/rect_conversions.h" |
| 16 #include "v8/include/v8.h" | 18 #include "v8/include/v8.h" |
| 17 | 19 |
| 18 using WebKit::WebFrame; | 20 using WebKit::WebFrame; |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 const char kSkiaBenchmarkingExtensionName[] = "v8/SkiaBenchmarking"; | 24 const char kSkiaBenchmarkingExtensionName[] = "v8/SkiaBenchmarking"; |
| 23 | 25 |
| 26 static scoped_refptr<cc::Picture> ParsePictureArg(v8::Handle<v8::Value> arg) { | |
| 27 scoped_ptr<content::V8ValueConverter> converter( | |
| 28 content::V8ValueConverter::create()); | |
| 29 | |
| 30 v8::String::Value v8_picture(arg); | |
| 31 scoped_ptr<base::Value> picture_value( | |
| 32 converter->FromV8Value(arg, v8::Context::GetCurrent())); | |
| 33 if (!picture_value) | |
| 34 return NULL; | |
| 35 | |
| 36 return cc::Picture::CreateFromValue(picture_value.get()); | |
| 37 } | |
| 38 | |
| 24 class SkiaBenchmarkingWrapper : public v8::Extension { | 39 class SkiaBenchmarkingWrapper : public v8::Extension { |
| 25 public: | 40 public: |
| 26 SkiaBenchmarkingWrapper() : | 41 SkiaBenchmarkingWrapper() : |
| 27 v8::Extension(kSkiaBenchmarkingExtensionName, | 42 v8::Extension(kSkiaBenchmarkingExtensionName, |
| 28 "if (typeof(chrome) == 'undefined') {" | 43 "if (typeof(chrome) == 'undefined') {" |
| 29 " chrome = {};" | 44 " chrome = {};" |
| 30 "};" | 45 "};" |
| 31 "if (typeof(chrome.skiaBenchmarking) == 'undefined') {" | 46 "if (typeof(chrome.skiaBenchmarking) == 'undefined') {" |
| 32 " chrome.skiaBenchmarking = {};" | 47 " chrome.skiaBenchmarking = {};" |
| 33 "};" | 48 "};" |
| 34 "chrome.skiaBenchmarking.rasterize = function(picture, scale, rect) {" | 49 "chrome.skiaBenchmarking.rasterize = function(picture, scale, rect) {" |
| 35 " /* " | 50 " /* " |
| 36 " Rasterizes a Picture JSON-encoded by cc::Picture::AsValue()." | 51 " Rasterizes a Picture JSON-encoded by cc::Picture::AsValue()." |
| 37 " @param {Object} picture A json-encoded cc::Picture." | 52 " @param {Object} picture A json-encoded cc::Picture." |
| 38 " @param {Number} scale (optional) Rendering scale." | 53 " @param {Number} scale (optional) Rendering scale." |
| 39 " @param [Number, Number, Number, Number] clip_rect (optional)." | 54 " @param [Number, Number, Number, Number] clip_rect (optional)." |
| 40 " @returns { 'width': {Number}, 'height': {Number}," | 55 " @returns { 'width': {Number}, 'height': {Number}," |
| 41 " 'data': {ArrayBuffer} }" | 56 " 'data': {ArrayBuffer} }" |
| 42 " */" | 57 " */" |
| 43 " native function Rasterize();" | 58 " native function Rasterize();" |
| 44 " return Rasterize(picture, scale, rect);" | 59 " return Rasterize(picture, scale, rect);" |
| 45 "};" | 60 "};" |
| 61 "chrome.skiaBenchmarking.getOps = function(picture) {" | |
| 62 " /* " | |
| 63 " Extracts the Skia draw commands from a JSON-encoded cc::Picture" | |
| 64 " @param {Object} picture A json-encoded cc::Picture." | |
| 65 " @returns [{ 'cmd': {String}, 'info': [String, ...] }, ...]" | |
|
nduca
2013/06/11 23:52:13
define in the docs that undefined is returned when
f(malita)
2013/06/12 13:32:37
Ok.
| |
| 66 " */" | |
| 67 " native function GetOps();" | |
| 68 " return GetOps(picture);" | |
| 69 "};" | |
| 46 ) { | 70 ) { |
| 47 content::SkiaBenchmarkingExtension::InitSkGraphics(); | 71 content::SkiaBenchmarkingExtension::InitSkGraphics(); |
| 48 } | 72 } |
| 49 | 73 |
| 50 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 74 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
| 51 v8::Handle<v8::String> name) OVERRIDE { | 75 v8::Handle<v8::String> name) OVERRIDE { |
| 52 if (name->Equals(v8::String::New("Rasterize"))) | 76 if (name->Equals(v8::String::New("Rasterize"))) |
| 53 return v8::FunctionTemplate::New(Rasterize); | 77 return v8::FunctionTemplate::New(Rasterize); |
| 78 if (name->Equals(v8::String::New("GetOps"))) | |
| 79 return v8::FunctionTemplate::New(GetOps); | |
| 54 | 80 |
| 55 return v8::Handle<v8::FunctionTemplate>(); | 81 return v8::Handle<v8::FunctionTemplate>(); |
| 56 } | 82 } |
| 57 | 83 |
| 58 static v8::Handle<v8::Value> Rasterize(const v8::Arguments& args) { | 84 static v8::Handle<v8::Value> Rasterize(const v8::Arguments& args) { |
| 59 if (args.Length() < 1) | 85 if (args.Length() < 1) |
| 60 return v8::Undefined(); | 86 return v8::Undefined(); |
| 61 | 87 |
| 62 WebFrame* web_frame = WebFrame::frameForCurrentContext(); | 88 scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]); |
| 63 if (!web_frame) | |
| 64 return v8::Undefined(); | |
| 65 | |
| 66 scoped_ptr<content::V8ValueConverter> converter( | |
| 67 content::V8ValueConverter::create()); | |
| 68 | |
| 69 v8::String::Value v8_picture(args[0]); | |
| 70 scoped_ptr<base::Value> picture_value( | |
| 71 converter->FromV8Value( | |
| 72 args[0], v8::Context::GetCurrent())); | |
| 73 if (!picture_value) | |
| 74 return v8::Undefined(); | |
| 75 | |
| 76 scoped_refptr<cc::Picture> picture = | |
| 77 cc::Picture::CreateFromValue(picture_value.get()); | |
| 78 if (!picture.get()) | 89 if (!picture.get()) |
| 79 return v8::Undefined(); | 90 return v8::Undefined(); |
| 80 | 91 |
| 81 float scale = 1.0f; | 92 float scale = 1.0f; |
| 82 if (args.Length() > 1 && args[1]->IsNumber()) | 93 if (args.Length() > 1 && args[1]->IsNumber()) |
| 83 scale = std::max(0.01, std::min(100.0, args[1]->NumberValue())); | 94 scale = std::max(0.01, std::min(100.0, args[1]->NumberValue())); |
| 84 | 95 |
| 85 gfx::RectF clip(picture->LayerRect()); | 96 gfx::RectF clip(picture->LayerRect()); |
| 86 if (args.Length() > 2 && args[2]->IsArray()) { | 97 if (args.Length() > 2 && args[2]->IsArray()) { |
| 87 v8::Array* a = v8::Array::Cast(*args[2]); | 98 v8::Array* a = v8::Array::Cast(*args[2]); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 | 144 |
| 134 v8::Handle<v8::Object> result = v8::Object::New(); | 145 v8::Handle<v8::Object> result = v8::Object::New(); |
| 135 result->Set(v8::String::New("width"), | 146 result->Set(v8::String::New("width"), |
| 136 v8::Number::New(snapped_clip.width())); | 147 v8::Number::New(snapped_clip.width())); |
| 137 result->Set(v8::String::New("height"), | 148 result->Set(v8::String::New("height"), |
| 138 v8::Number::New(snapped_clip.height())); | 149 v8::Number::New(snapped_clip.height())); |
| 139 result->Set(v8::String::New("data"), buffer.toV8Value()); | 150 result->Set(v8::String::New("data"), buffer.toV8Value()); |
| 140 | 151 |
| 141 return result; | 152 return result; |
| 142 } | 153 } |
| 154 | |
| 155 static v8::Handle<v8::Value> GetOps(const v8::Arguments& args) { | |
| 156 if (args.Length() != 1) | |
| 157 return v8::Undefined(); | |
| 158 | |
| 159 scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]); | |
| 160 if (!picture.get()) | |
| 161 return v8::Undefined(); | |
| 162 | |
| 163 gfx::Rect bounds = picture->LayerRect(); | |
| 164 SkDebugCanvas canvas(bounds.width(), bounds.height()); | |
| 165 canvas.setBounds(bounds.width(), bounds.height()); | |
| 166 picture->Raster(&canvas, NULL, bounds, 1.0f); | |
| 167 | |
| 168 v8::Local<v8::Array> result = v8::Array::New(canvas.getSize()); | |
| 169 for (int i = 0; i < canvas.getSize(); ++i) { | |
| 170 v8::Handle<v8::Object> cmd = v8::Object::New(); | |
| 171 cmd->Set(v8::String::New("cmd"), v8::String::New( | |
| 172 SkDrawCommand::GetCommandString( | |
| 173 canvas.getDrawCommandAt(i)->getType()))); | |
| 174 | |
| 175 SkTDArray<SkString*>* info = canvas.getCommandInfo(i); | |
|
nduca
2013/06/11 23:52:13
what is in the info? what is mandatory and what is
f(malita)
2013/06/12 13:32:37
This is based on the current Skia debugger backend
| |
| 176 if (info) { | |
|
nduca
2013/06/11 23:52:13
why would info not be returned? It seems odd that
f(malita)
2013/06/12 13:32:37
Was following Skia use here, but you're right - it
| |
| 177 v8::Local<v8::Array> v8_info = v8::Array::New(info->count()); | |
| 178 for (int j = 0; j < info->count(); ++j) | |
| 179 v8_info->Set(j, v8::String::New(info->getAt(j)->c_str())); | |
| 180 | |
| 181 cmd->Set(v8::String::New("info"), v8_info); | |
| 182 } | |
| 183 | |
| 184 result->Set(i, cmd); | |
| 185 } | |
| 186 | |
| 187 return result; | |
| 188 } | |
| 143 }; | 189 }; |
| 144 | 190 |
| 145 } // namespace | 191 } // namespace |
| 146 | 192 |
| 147 namespace content { | 193 namespace content { |
| 148 | 194 |
| 149 v8::Extension* SkiaBenchmarkingExtension::Get() { | 195 v8::Extension* SkiaBenchmarkingExtension::Get() { |
| 150 return new SkiaBenchmarkingWrapper(); | 196 return new SkiaBenchmarkingWrapper(); |
| 151 } | 197 } |
| 152 | 198 |
| 153 void SkiaBenchmarkingExtension::InitSkGraphics() { | 199 void SkiaBenchmarkingExtension::InitSkGraphics() { |
| 154 // Always call on the main render thread. | 200 // Always call on the main render thread. |
| 155 // Does not need to be thread-safe, as long as the above holds. | 201 // Does not need to be thread-safe, as long as the above holds. |
| 156 // FIXME: remove this after Skia updates SkGraphics::Init() to be | 202 // FIXME: remove this after Skia updates SkGraphics::Init() to be |
| 157 // thread-safe and idempotent. | 203 // thread-safe and idempotent. |
| 158 static bool skia_initialized = false; | 204 static bool skia_initialized = false; |
| 159 if (!skia_initialized) { | 205 if (!skia_initialized) { |
| 160 SkGraphics::Init(); | 206 SkGraphics::Init(); |
| 161 skia_initialized = true; | 207 skia_initialized = true; |
| 162 } | 208 } |
| 163 } | 209 } |
| 164 | 210 |
| 165 } // namespace content | 211 } // namespace content |
| OLD | NEW |