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 |