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} }" |
57 " @returns undefined if the arguments are invalid or the picture" | |
58 " version is not supported." | |
42 " */" | 59 " */" |
43 " native function Rasterize();" | 60 " native function Rasterize();" |
44 " return Rasterize(picture, scale, rect);" | 61 " return Rasterize(picture, scale, rect);" |
45 "};" | 62 "};" |
63 "chrome.skiaBenchmarking.getOps = function(picture) {" | |
64 " /* " | |
65 " Extracts the Skia draw commands from a JSON-encoded cc::Picture" | |
66 " @param {Object} picture A json-encoded cc::Picture." | |
67 " @returns [{ 'cmd': {String}, 'info': [String, ...] }, ...]" | |
68 " @returns undefined if the arguments are invalid or the picture" | |
69 " version is not supported." | |
70 " */" | |
71 " native function GetOps();" | |
72 " return GetOps(picture);" | |
73 "};" | |
46 ) { | 74 ) { |
47 content::SkiaBenchmarkingExtension::InitSkGraphics(); | 75 content::SkiaBenchmarkingExtension::InitSkGraphics(); |
48 } | 76 } |
49 | 77 |
50 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 78 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
51 v8::Handle<v8::String> name) OVERRIDE { | 79 v8::Handle<v8::String> name) OVERRIDE { |
52 if (name->Equals(v8::String::New("Rasterize"))) | 80 if (name->Equals(v8::String::New("Rasterize"))) |
53 return v8::FunctionTemplate::New(Rasterize); | 81 return v8::FunctionTemplate::New(Rasterize); |
82 if (name->Equals(v8::String::New("GetOps"))) | |
83 return v8::FunctionTemplate::New(GetOps); | |
54 | 84 |
55 return v8::Handle<v8::FunctionTemplate>(); | 85 return v8::Handle<v8::FunctionTemplate>(); |
56 } | 86 } |
57 | 87 |
58 static void Rasterize(const v8::FunctionCallbackInfo<v8::Value>& args) { | 88 static void Rasterize(const v8::FunctionCallbackInfo<v8::Value>& args) { |
59 if (args.Length() < 1) | 89 if (args.Length() < 1) |
60 return; | 90 return; |
61 | 91 |
62 WebFrame* web_frame = WebFrame::frameForCurrentContext(); | 92 scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]); |
63 if (!web_frame) | |
64 return; | |
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; | |
75 | |
76 scoped_refptr<cc::Picture> picture = | |
77 cc::Picture::CreateFromValue(picture_value.get()); | |
78 if (!picture.get()) | 93 if (!picture.get()) |
79 return; | 94 return; |
80 | 95 |
81 float scale = 1.0f; | 96 float scale = 1.0f; |
82 if (args.Length() > 1 && args[1]->IsNumber()) | 97 if (args.Length() > 1 && args[1]->IsNumber()) |
83 scale = std::max(0.01, std::min(100.0, args[1]->NumberValue())); | 98 scale = std::max(0.01, std::min(100.0, args[1]->NumberValue())); |
84 | 99 |
85 gfx::RectF clip(picture->LayerRect()); | 100 gfx::RectF clip(picture->LayerRect()); |
86 if (args.Length() > 2 && args[2]->IsArray()) { | 101 if (args.Length() > 2 && args[2]->IsArray()) { |
87 v8::Array* a = v8::Array::Cast(*args[2]); | 102 v8::Array* a = v8::Array::Cast(*args[2]); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 | 148 |
134 v8::Handle<v8::Object> result = v8::Object::New(); | 149 v8::Handle<v8::Object> result = v8::Object::New(); |
135 result->Set(v8::String::New("width"), | 150 result->Set(v8::String::New("width"), |
136 v8::Number::New(snapped_clip.width())); | 151 v8::Number::New(snapped_clip.width())); |
137 result->Set(v8::String::New("height"), | 152 result->Set(v8::String::New("height"), |
138 v8::Number::New(snapped_clip.height())); | 153 v8::Number::New(snapped_clip.height())); |
139 result->Set(v8::String::New("data"), buffer.toV8Value()); | 154 result->Set(v8::String::New("data"), buffer.toV8Value()); |
140 | 155 |
141 args.GetReturnValue().Set(result); | 156 args.GetReturnValue().Set(result); |
142 } | 157 } |
158 | |
159 static void GetOps(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
160 if (args.Length() != 1) | |
161 return; | |
162 | |
163 scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]); | |
piman
2013/06/20 18:30:52
Just to confirm, this extension is behind a flag,
f(malita)
2013/06/20 18:48:15
Yes, this is all behind --enable-skia-benchmarking
| |
164 if (!picture.get()) | |
165 return; | |
166 | |
167 gfx::Rect bounds = picture->LayerRect(); | |
168 SkDebugCanvas canvas(bounds.width(), bounds.height()); | |
169 picture->Raster(&canvas, NULL, bounds, 1.0f); | |
170 | |
171 v8::Local<v8::Array> result = v8::Array::New(canvas.getSize()); | |
172 for (int i = 0; i < canvas.getSize(); ++i) { | |
173 DrawType cmd_type = canvas.getDrawCommandAt(i)->getType(); | |
174 v8::Handle<v8::Object> cmd = v8::Object::New(); | |
175 cmd->Set(v8::String::New("cmd_type"), v8::Integer::New(cmd_type)); | |
176 cmd->Set(v8::String::New("cmd_string"), v8::String::New( | |
177 SkDrawCommand::GetCommandString(cmd_type))); | |
178 | |
179 SkTDArray<SkString*>* info = canvas.getCommandInfo(i); | |
180 DCHECK(info); | |
181 | |
182 v8::Local<v8::Array> v8_info = v8::Array::New(info->count()); | |
183 for (int j = 0; j < info->count(); ++j) { | |
184 const SkString* info_str = (*info)[j]; | |
185 DCHECK(info_str); | |
186 v8_info->Set(j, v8::String::New(info_str->c_str())); | |
187 } | |
188 | |
189 cmd->Set(v8::String::New("info"), v8_info); | |
190 | |
191 result->Set(i, cmd); | |
192 } | |
193 | |
194 args.GetReturnValue().Set(result); | |
195 } | |
143 }; | 196 }; |
144 | 197 |
145 } // namespace | 198 } // namespace |
146 | 199 |
147 namespace content { | 200 namespace content { |
148 | 201 |
149 v8::Extension* SkiaBenchmarkingExtension::Get() { | 202 v8::Extension* SkiaBenchmarkingExtension::Get() { |
150 return new SkiaBenchmarkingWrapper(); | 203 return new SkiaBenchmarkingWrapper(); |
151 } | 204 } |
152 | 205 |
153 void SkiaBenchmarkingExtension::InitSkGraphics() { | 206 void SkiaBenchmarkingExtension::InitSkGraphics() { |
154 // Always call on the main render thread. | 207 // Always call on the main render thread. |
155 // Does not need to be thread-safe, as long as the above holds. | 208 // Does not need to be thread-safe, as long as the above holds. |
156 // FIXME: remove this after Skia updates SkGraphics::Init() to be | 209 // FIXME: remove this after Skia updates SkGraphics::Init() to be |
157 // thread-safe and idempotent. | 210 // thread-safe and idempotent. |
158 static bool skia_initialized = false; | 211 static bool skia_initialized = false; |
159 if (!skia_initialized) { | 212 if (!skia_initialized) { |
160 SkGraphics::Init(); | 213 SkGraphics::Init(); |
161 skia_initialized = true; | 214 skia_initialized = true; |
162 } | 215 } |
163 } | 216 } |
164 | 217 |
165 } // namespace content | 218 } // namespace content |
OLD | NEW |