Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(939)

Side by Side Diff: content/renderer/gpu/gpu_benchmarking_extension.cc

Issue 647433003: Convert GpuBenchmarkingExtension to a gin::Wrappable class (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/gpu/gpu_benchmarking_extension.h" 5 #include "content/renderer/gpu/gpu_benchmarking_extension.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/memory/scoped_vector.h" 12 #include "base/memory/scoped_vector.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "cc/layers/layer.h" 14 #include "cc/layers/layer.h"
15 #include "content/common/input/synthetic_gesture_params.h" 15 #include "content/common/input/synthetic_gesture_params.h"
16 #include "content/common/input/synthetic_pinch_gesture_params.h" 16 #include "content/common/input/synthetic_pinch_gesture_params.h"
17 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h" 17 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
18 #include "content/common/input/synthetic_tap_gesture_params.h" 18 #include "content/common/input/synthetic_tap_gesture_params.h"
19 #include "content/public/renderer/render_thread.h" 19 #include "content/public/renderer/render_thread.h"
20 #include "content/public/renderer/v8_value_converter.h" 20 #include "content/public/renderer/v8_value_converter.h"
21 #include "content/renderer/chrome_object_extensions_utils.h"
21 #include "content/renderer/gpu/render_widget_compositor.h" 22 #include "content/renderer/gpu/render_widget_compositor.h"
22 #include "content/renderer/render_thread_impl.h" 23 #include "content/renderer/render_thread_impl.h"
23 #include "content/renderer/render_view_impl.h" 24 #include "content/renderer/render_view_impl.h"
24 #include "content/renderer/skia_benchmarking_extension.h" 25 #include "content/renderer/skia_benchmarking_extension.h"
26 #include "gin/arguments.h"
27 #include "gin/handle.h"
28 #include "gin/object_template_builder.h"
25 #include "third_party/WebKit/public/web/WebImageCache.h" 29 #include "third_party/WebKit/public/web/WebImageCache.h"
30 #include "third_party/WebKit/public/web/WebKit.h"
26 #include "third_party/WebKit/public/web/WebLocalFrame.h" 31 #include "third_party/WebKit/public/web/WebLocalFrame.h"
27 #include "third_party/WebKit/public/web/WebView.h" 32 #include "third_party/WebKit/public/web/WebView.h"
28 #include "third_party/skia/include/core/SkData.h" 33 #include "third_party/skia/include/core/SkData.h"
29 #include "third_party/skia/include/core/SkGraphics.h" 34 #include "third_party/skia/include/core/SkGraphics.h"
30 #include "third_party/skia/include/core/SkPicture.h" 35 #include "third_party/skia/include/core/SkPicture.h"
31 #include "third_party/skia/include/core/SkPixelRef.h" 36 #include "third_party/skia/include/core/SkPixelRef.h"
32 #include "third_party/skia/include/core/SkStream.h" 37 #include "third_party/skia/include/core/SkStream.h"
33 #include "ui/gfx/codec/png_codec.h" 38 #include "ui/gfx/codec/png_codec.h"
34 #include "v8/include/v8.h" 39 #include "v8/include/v8.h"
35 40
36 using blink::WebCanvas; 41 using blink::WebCanvas;
37 using blink::WebLocalFrame; 42 using blink::WebLocalFrame;
38 using blink::WebImageCache; 43 using blink::WebImageCache;
39 using blink::WebPrivatePtr; 44 using blink::WebPrivatePtr;
40 using blink::WebSize; 45 using blink::WebSize;
41 using blink::WebView; 46 using blink::WebView;
42 47
43 const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking"; 48 namespace content {
49
50 namespace {
44 51
45 // offset parameter is deprecated/ignored, and will be remove from the 52 // offset parameter is deprecated/ignored, and will be remove from the
46 // signature in a future skia release. <reed@google.com> 53 // signature in a future skia release. <reed@google.com>
47 static SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) { 54 SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
48 SkPixelRef* pr = bm.pixelRef(); 55 SkPixelRef* pr = bm.pixelRef();
49 if (pr != NULL) { 56 if (pr != NULL) {
50 SkData* data = pr->refEncodedData(); 57 SkData* data = pr->refEncodedData();
51 if (data != NULL) 58 if (data != NULL)
52 return data; 59 return data;
53 } 60 }
54 std::vector<unsigned char> vector; 61 std::vector<unsigned char> vector;
55 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) { 62 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
56 return SkData::NewWithCopy(&vector.front() , vector.size()); 63 return SkData::NewWithCopy(&vector.front(), vector.size());
57 } 64 }
58 return NULL; 65 return NULL;
59 } 66 }
60 67
61 namespace {
62
63 class SkPictureSerializer { 68 class SkPictureSerializer {
64 public: 69 public:
65 explicit SkPictureSerializer(const base::FilePath& dirpath) 70 explicit SkPictureSerializer(const base::FilePath& dirpath)
66 : dirpath_(dirpath), 71 : dirpath_(dirpath),
67 layer_id_(0) { 72 layer_id_(0) {
68 // Let skia register known effect subclasses. This basically enables 73 // Let skia register known effect subclasses. This basically enables
69 // reflection on those subclasses required for picture serialization. 74 // reflection on those subclasses required for picture serialization.
70 content::SkiaBenchmarking::Initialize(); 75 SkiaBenchmarking::Initialize();
71 } 76 }
72 77
73 // Recursively serializes the layer tree. 78 // Recursively serializes the layer tree.
74 // Each layer in the tree is serialized into a separate skp file 79 // Each layer in the tree is serialized into a separate skp file
75 // in the given directory. 80 // in the given directory.
76 void Serialize(const cc::Layer* layer) { 81 void Serialize(const cc::Layer* layer) {
77 const cc::LayerList& children = layer->children(); 82 const cc::LayerList& children = layer->children();
78 for (size_t i = 0; i < children.size(); ++i) { 83 for (size_t i = 0; i < children.size(); ++i) {
79 Serialize(children[i].get()); 84 Serialize(children[i].get());
80 } 85 }
(...skipping 12 matching lines...) Expand all
93 SkFILEWStream file(filepath.c_str()); 98 SkFILEWStream file(filepath.c_str());
94 DCHECK(file.isValid()); 99 DCHECK(file.isValid());
95 picture->serialize(&file, &EncodeBitmapToData); 100 picture->serialize(&file, &EncodeBitmapToData);
96 } 101 }
97 102
98 private: 103 private:
99 base::FilePath dirpath_; 104 base::FilePath dirpath_;
100 int layer_id_; 105 int layer_id_;
101 }; 106 };
102 107
103 } // namespace 108 template <typename T>
109 bool GetArg(gin::Arguments* args, T* value) {
110 if (!args->GetNext(value)) {
111 args->ThrowError();
112 return false;
113 }
114 return true;
115 }
104 116
105 namespace content { 117 template <>
118 bool GetArg(gin::Arguments* args, int* value) {
119 float number;
120 bool ret = GetArg(args, &number);
121 *value = number;
122 return ret;
123 }
106 124
107 namespace { 125 template <typename T>
126 bool GetOptionalArg(gin::Arguments* args, T* value) {
127 if (args->PeekNext().IsEmpty())
128 return true;
129 if (args->PeekNext()->IsUndefined()) {
130 args->Skip();
131 return true;
132 }
133 return GetArg(args, value);
134 }
108 135
109 class CallbackAndContext : public base::RefCounted<CallbackAndContext> { 136 class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
110 public: 137 public:
111 CallbackAndContext(v8::Isolate* isolate, 138 CallbackAndContext(v8::Isolate* isolate,
112 v8::Handle<v8::Function> callback, 139 v8::Handle<v8::Function> callback,
113 v8::Handle<v8::Context> context) 140 v8::Handle<v8::Context> context)
114 : isolate_(isolate) { 141 : isolate_(isolate) {
115 callback_.Reset(isolate_, callback); 142 callback_.Reset(isolate_, callback);
116 context_.Reset(isolate_, context); 143 context_.Reset(isolate_, context);
117 } 144 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 228
202 private: 229 private:
203 WebLocalFrame* web_frame_; 230 WebLocalFrame* web_frame_;
204 WebView* web_view_; 231 WebView* web_view_;
205 RenderViewImpl* render_view_impl_; 232 RenderViewImpl* render_view_impl_;
206 RenderWidgetCompositor* compositor_; 233 RenderWidgetCompositor* compositor_;
207 234
208 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext); 235 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
209 }; 236 };
210 237
211 } // namespace 238 void OnMicroBenchmarkCompleted(
212 239 CallbackAndContext* callback_and_context,
213 class GpuBenchmarkingWrapper : public v8::Extension { 240 scoped_ptr<base::Value> result) {
214 public: 241 v8::Isolate* isolate = callback_and_context->isolate();
215 GpuBenchmarkingWrapper() : 242 v8::HandleScope scope(isolate);
216 v8::Extension(kGpuBenchmarkingExtensionName, 243 v8::Handle<v8::Context> context = callback_and_context->GetContext();
217 "if (typeof(chrome) == 'undefined') {" 244 v8::Context::Scope context_scope(context);
218 " chrome = {};" 245 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
219 "};" 246 if (frame) {
220 "if (typeof(chrome.gpuBenchmarking) == 'undefined') {"
221 " chrome.gpuBenchmarking = {};"
222 "};"
223 "chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers = function() {"
224 " native function SetNeedsDisplayOnAllLayers();"
225 " return SetNeedsDisplayOnAllLayers();"
226 "};"
227 "chrome.gpuBenchmarking.setRasterizeOnlyVisibleContent = "
228 "function() {"
229 " native function SetRasterizeOnlyVisibleContent();"
230 " return SetRasterizeOnlyVisibleContent();"
231 "};"
232 "chrome.gpuBenchmarking.printToSkPicture = function(dirname) {"
233 " native function PrintToSkPicture();"
234 " return PrintToSkPicture(dirname);"
235 "};"
236 "chrome.gpuBenchmarking.DEFAULT_INPUT = 0;"
237 "chrome.gpuBenchmarking.TOUCH_INPUT = 1;"
238 "chrome.gpuBenchmarking.MOUSE_INPUT = 2;"
239 "chrome.gpuBenchmarking.gestureSourceTypeSupported = "
240 " function(gesture_source_type) {"
241 " native function GestureSourceTypeSupported();"
242 " return GestureSourceTypeSupported(gesture_source_type);"
243 "};"
244 "chrome.gpuBenchmarking.smoothScrollBy = "
245 " function(pixels_to_scroll, opt_callback, opt_start_x,"
246 " opt_start_y, opt_gesture_source_type,"
247 " opt_direction, opt_speed_in_pixels_s) {"
248 " pixels_to_scroll = pixels_to_scroll || 0;"
249 " callback = opt_callback || function() { };"
250 " gesture_source_type = opt_gesture_source_type ||"
251 " chrome.gpuBenchmarking.DEFAULT_INPUT;"
252 " direction = opt_direction || 'down';"
253 " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
254 " native function BeginSmoothScroll();"
255 " return BeginSmoothScroll(pixels_to_scroll, callback,"
256 " gesture_source_type, direction,"
257 " speed_in_pixels_s, true,"
258 " opt_start_x, opt_start_y);"
259 "};"
260 "chrome.gpuBenchmarking.swipe = "
261 " function(direction, distance, opt_callback,"
262 " opt_start_x, opt_start_y,"
263 " opt_speed_in_pixels_s) {"
264 " direction = direction || 'up';"
265 " distance = distance || 0;"
266 " callback = opt_callback || function() { };"
267 " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
268 " native function BeginSmoothScroll();"
269 " return BeginSmoothScroll(-distance, callback,"
270 " chrome.gpuBenchmarking.TOUCH_INPUT,"
271 " direction, speed_in_pixels_s, false,"
272 " opt_start_x, opt_start_y);"
273 "};"
274 "chrome.gpuBenchmarking.scrollBounce = "
275 " function(direction, distance, overscroll, opt_repeat_count,"
276 " opt_callback, opt_start_x, opt_start_y,"
277 " opt_speed_in_pixels_s) {"
278 " direction = direction || 'down';"
279 " distance = distance || 0;"
280 " overscroll = overscroll || 0;"
281 " repeat_count = opt_repeat_count || 1;"
282 " callback = opt_callback || function() { };"
283 " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
284 " native function BeginScrollBounce();"
285 " return BeginScrollBounce(direction, distance, overscroll,"
286 " repeat_count, callback,"
287 " speed_in_pixels_s,"
288 " opt_start_x, opt_start_y);"
289 "};"
290 // TODO(dominikg): Remove once JS interface changes have rolled into
291 // stable.
292 "chrome.gpuBenchmarking.newPinchInterface = true;"
293 "chrome.gpuBenchmarking.pinchBy = "
294 " function(scale_factor, anchor_x, anchor_y,"
295 " opt_callback, "
296 "opt_relative_pointer_speed_in_pixels_s) {"
297 " callback = opt_callback || function() { };"
298 " relative_pointer_speed_in_pixels_s ="
299 " opt_relative_pointer_speed_in_pixels_s || 800;"
300 " native function BeginPinch();"
301 " return BeginPinch(scale_factor, anchor_x, anchor_y, callback,"
302 " relative_pointer_speed_in_pixels_s);"
303 "};"
304 "chrome.gpuBenchmarking.tap = "
305 " function(position_x, position_y, opt_callback, "
306 "opt_duration_ms,"
307 " opt_gesture_source_type) {"
308 " callback = opt_callback || function() { };"
309 " duration_ms = opt_duration_ms || 50;"
310 " gesture_source_type = opt_gesture_source_type ||"
311 " chrome.gpuBenchmarking.DEFAULT_INPUT;"
312 " native function BeginTap();"
313 " return BeginTap(position_x, position_y, callback, duration_ms,"
314 " gesture_source_type);"
315 "};"
316 "chrome.gpuBenchmarking.beginWindowSnapshotPNG = "
317 "function(callback) {"
318 " native function BeginWindowSnapshotPNG();"
319 " BeginWindowSnapshotPNG(callback);"
320 "};"
321 "chrome.gpuBenchmarking.clearImageCache = function() {"
322 " native function ClearImageCache();"
323 " ClearImageCache();"
324 "};"
325 "chrome.gpuBenchmarking.runMicroBenchmark ="
326 " function(name, callback, opt_arguments) {"
327 " arguments = opt_arguments || {};"
328 " native function RunMicroBenchmark();"
329 " return RunMicroBenchmark(name, callback, arguments);"
330 "};"
331 "chrome.gpuBenchmarking.sendMessageToMicroBenchmark ="
332 " function(id, arguments) {"
333 " native function SendMessageToMicroBenchmark();"
334 " return SendMessageToMicroBenchmark(id, arguments);"
335 "};"
336 "chrome.gpuBenchmarking.hasGpuProcess = function() {"
337 " native function HasGpuProcess();"
338 " return HasGpuProcess();"
339 "};") {}
340
341 v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
342 v8::Isolate* isolate,
343 v8::Handle<v8::String> name) override {
344 if (name->Equals(
345 v8::String::NewFromUtf8(isolate, "SetNeedsDisplayOnAllLayers")))
346 return v8::FunctionTemplate::New(isolate, SetNeedsDisplayOnAllLayers);
347 if (name->Equals(
348 v8::String::NewFromUtf8(isolate, "SetRasterizeOnlyVisibleContent")))
349 return v8::FunctionTemplate::New(isolate, SetRasterizeOnlyVisibleContent);
350 if (name->Equals(v8::String::NewFromUtf8(isolate, "PrintToSkPicture")))
351 return v8::FunctionTemplate::New(isolate, PrintToSkPicture);
352 if (name->Equals(
353 v8::String::NewFromUtf8(isolate, "GestureSourceTypeSupported")))
354 return v8::FunctionTemplate::New(isolate, GestureSourceTypeSupported);
355 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginSmoothScroll")))
356 return v8::FunctionTemplate::New(isolate, BeginSmoothScroll);
357 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginScrollBounce")))
358 return v8::FunctionTemplate::New(isolate, BeginScrollBounce);
359 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginPinch")))
360 return v8::FunctionTemplate::New(isolate, BeginPinch);
361 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginTap")))
362 return v8::FunctionTemplate::New(isolate, BeginTap);
363 if (name->Equals(
364 v8::String::NewFromUtf8(isolate, "BeginWindowSnapshotPNG")))
365 return v8::FunctionTemplate::New(isolate, BeginWindowSnapshotPNG);
366 if (name->Equals(v8::String::NewFromUtf8(isolate, "ClearImageCache")))
367 return v8::FunctionTemplate::New(isolate, ClearImageCache);
368 if (name->Equals(v8::String::NewFromUtf8(isolate, "RunMicroBenchmark")))
369 return v8::FunctionTemplate::New(isolate, RunMicroBenchmark);
370 if (name->Equals(
371 v8::String::NewFromUtf8(isolate, "SendMessageToMicroBenchmark")))
372 return v8::FunctionTemplate::New(isolate, SendMessageToMicroBenchmark);
373 if (name->Equals(v8::String::NewFromUtf8(isolate, "HasGpuProcess")))
374 return v8::FunctionTemplate::New(isolate, HasGpuProcess);
375
376 return v8::Handle<v8::FunctionTemplate>();
377 }
378
379 static void SetNeedsDisplayOnAllLayers(
380 const v8::FunctionCallbackInfo<v8::Value>& args) {
381 GpuBenchmarkingContext context;
382 if (!context.Init(true))
383 return;
384
385 context.compositor()->SetNeedsDisplayOnAllLayers();
386 }
387
388 static void SetRasterizeOnlyVisibleContent(
389 const v8::FunctionCallbackInfo<v8::Value>& args) {
390 GpuBenchmarkingContext context;
391 if (!context.Init(true))
392 return;
393
394 context.compositor()->SetRasterizeOnlyVisibleContent();
395 }
396
397 static void PrintToSkPicture(
398 const v8::FunctionCallbackInfo<v8::Value>& args) {
399 if (args.Length() != 1)
400 return;
401
402 v8::String::Utf8Value dirname(args[0]);
403 if (dirname.length() == 0)
404 return;
405
406 GpuBenchmarkingContext context;
407 if (!context.Init(true))
408 return;
409
410 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
411 if (!root_layer)
412 return;
413
414 base::FilePath dirpath(
415 base::FilePath::StringType(*dirname, *dirname + dirname.length()));
416 if (!base::CreateDirectory(dirpath) ||
417 !base::PathIsWritable(dirpath)) {
418 std::string msg("Path is not writable: ");
419 msg.append(dirpath.MaybeAsASCII());
420 v8::Isolate* isolate = args.GetIsolate();
421 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
422 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
423 return;
424 }
425
426 SkPictureSerializer serializer(dirpath);
427 serializer.Serialize(root_layer);
428 }
429
430 static void OnSyntheticGestureCompleted(
431 CallbackAndContext* callback_and_context) {
432 v8::Isolate* isolate = callback_and_context->isolate();
433 v8::HandleScope scope(isolate);
434 v8::Handle<v8::Context> context = callback_and_context->GetContext();
435 v8::Context::Scope context_scope(context);
436 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
437 if (frame) {
438 frame->callFunctionEvenIfScriptDisabled(
439 callback_and_context->GetCallback(),
440 v8::Object::New(isolate),
441 0,
442 NULL);
443 }
444 }
445
446 static void GestureSourceTypeSupported(
447 const v8::FunctionCallbackInfo<v8::Value>& args) {
448 if (args.Length() != 1 || !args[0]->IsNumber()) {
449 args.GetReturnValue().Set(false);
450 return;
451 }
452
453 int gesture_source_type = args[0]->IntegerValue();
454 if (gesture_source_type < 0 ||
455 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
456 args.GetReturnValue().Set(false);
457 return;
458 }
459
460 bool is_supported = SyntheticGestureParams::IsGestureSourceTypeSupported(
461 static_cast<SyntheticGestureParams::GestureSourceType>(
462 gesture_source_type));
463 args.GetReturnValue().Set(is_supported);
464 }
465
466 static void BeginSmoothScroll(
467 const v8::FunctionCallbackInfo<v8::Value>& args) {
468 GpuBenchmarkingContext context;
469 if (!context.Init(false))
470 return;
471
472 // The last two arguments can be undefined. We check their validity later.
473 int arglen = args.Length();
474 if (arglen < 8 ||
475 !args[0]->IsNumber() ||
476 !args[1]->IsFunction() ||
477 !args[2]->IsNumber() ||
478 !args[3]->IsString() ||
479 !args[4]->IsNumber() ||
480 !args[5]->IsBoolean()) {
481 args.GetReturnValue().Set(false);
482 return;
483 }
484
485 v8::Local<v8::Function> callback_local =
486 v8::Local<v8::Function>::Cast(args[1]);
487
488 scoped_refptr<CallbackAndContext> callback_and_context =
489 new CallbackAndContext(args.GetIsolate(),
490 callback_local,
491 context.web_frame()->mainWorldScriptContext());
492
493 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
494 new SyntheticSmoothScrollGestureParams);
495
496 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
497 float page_scale_factor = context.web_view()->pageScaleFactor();
498
499 int gesture_source_type = args[2]->IntegerValue();
500 if (gesture_source_type < 0 ||
501 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
502 args.GetReturnValue().Set(false);
503 return;
504 }
505 gesture_params->gesture_source_type =
506 static_cast<SyntheticGestureParams::GestureSourceType>(
507 gesture_source_type);
508
509 gesture_params->speed_in_pixels_s = args[4]->IntegerValue();
510 gesture_params->prevent_fling = args[5]->BooleanValue();
511
512 // Account for the 2 optional arguments, start_x and start_y.
513 gfx::Point anchor;
514 if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
515 blink::WebRect rect = context.render_view_impl()->windowRect();
516 anchor.SetPoint(rect.width / 2, rect.height / 2);
517 } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
518 anchor.SetPoint(args[6]->IntegerValue() * page_scale_factor,
519 args[7]->IntegerValue() * page_scale_factor);
520 } else {
521 args.GetReturnValue().Set(false);
522 return;
523 }
524 gesture_params->anchor = anchor;
525
526 int distance_length = args[0]->IntegerValue() * page_scale_factor;
527 gfx::Vector2d distance;
528 v8::String::Utf8Value direction(args[3]);
529 DCHECK(*direction);
530 std::string direction_str(*direction);
531 if (direction_str == "down")
532 distance.set_y(-distance_length);
533 else if (direction_str == "up")
534 distance.set_y(distance_length);
535 else if (direction_str == "right")
536 distance.set_x(-distance_length);
537 else if (direction_str == "left")
538 distance.set_x(distance_length);
539 else {
540 args.GetReturnValue().Set(false);
541 return;
542 }
543 gesture_params->distances.push_back(distance);
544
545 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
546 // progress, we will leak the callback and context. This needs to be fixed,
547 // somehow.
548 context.render_view_impl()->QueueSyntheticGesture(
549 gesture_params.Pass(),
550 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
551
552 args.GetReturnValue().Set(true);
553 }
554
555 static void BeginScrollBounce(
556 const v8::FunctionCallbackInfo<v8::Value>& args) {
557 GpuBenchmarkingContext context;
558 if (!context.Init(false))
559 return;
560
561 // The last two arguments can be undefined. We check their validity later.
562 int arglen = args.Length();
563 if (arglen < 8 ||
564 !args[0]->IsString() ||
565 !args[1]->IsNumber() ||
566 !args[2]->IsNumber() ||
567 !args[3]->IsNumber() ||
568 !args[4]->IsFunction() ||
569 !args[5]->IsNumber()) {
570 args.GetReturnValue().Set(false);
571 return;
572 }
573
574 v8::Local<v8::Function> callback_local =
575 v8::Local<v8::Function>::Cast(args[4]);
576
577 scoped_refptr<CallbackAndContext> callback_and_context =
578 new CallbackAndContext(args.GetIsolate(),
579 callback_local,
580 context.web_frame()->mainWorldScriptContext());
581
582 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
583 new SyntheticSmoothScrollGestureParams);
584
585 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
586 float page_scale_factor = context.web_view()->pageScaleFactor();
587
588 gesture_params->speed_in_pixels_s = args[5]->IntegerValue();
589
590 // Account for the 2 optional arguments, start_x and start_y.
591 gfx::Point start;
592 if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
593 blink::WebRect rect = context.render_view_impl()->windowRect();
594 start.SetPoint(rect.width / 2, rect.height / 2);
595 } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
596 start.SetPoint(args[6]->IntegerValue() * page_scale_factor,
597 args[7]->IntegerValue() * page_scale_factor);
598 } else {
599 args.GetReturnValue().Set(false);
600 return;
601 }
602
603 int distance_length = args[1]->IntegerValue() * page_scale_factor;
604 int overscroll_length = args[2]->IntegerValue() * page_scale_factor;
605 gfx::Vector2d distance;
606 gfx::Vector2d overscroll;
607 v8::String::Utf8Value direction(args[0]);
608 DCHECK(*direction);
609 std::string direction_str(*direction);
610 if (direction_str == "down") {
611 distance.set_y(-distance_length);
612 overscroll.set_y(overscroll_length);
613 }
614 else if (direction_str == "up") {
615 distance.set_y(distance_length);
616 overscroll.set_y(-overscroll_length);
617 }
618 else if (direction_str == "right") {
619 distance.set_x(-distance_length);
620 overscroll.set_x(overscroll_length);
621 }
622 else if (direction_str == "left") {
623 distance.set_x(distance_length);
624 overscroll.set_x(-overscroll_length);
625 }
626 else {
627 args.GetReturnValue().Set(false);
628 return;
629 }
630
631 int repeat_count = args[3]->IntegerValue();
632 gesture_params->anchor = start;
633 for (int i = 0; i < repeat_count; i++) {
634 gesture_params->distances.push_back(distance);
635 gesture_params->distances.push_back(-distance + overscroll);
636 }
637
638 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
639 // progress, we will leak the callback and context. This needs to be fixed,
640 // somehow.
641 context.render_view_impl()->QueueSyntheticGesture(
642 gesture_params.Pass(),
643 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
644
645 args.GetReturnValue().Set(true);
646 }
647
648 static void BeginPinch(
649 const v8::FunctionCallbackInfo<v8::Value>& args) {
650 GpuBenchmarkingContext context;
651 if (!context.Init(false))
652 return;
653
654 int arglen = args.Length();
655 if (arglen < 5 ||
656 !args[0]->IsNumber() ||
657 !args[1]->IsNumber() ||
658 !args[2]->IsNumber() ||
659 !args[3]->IsFunction() ||
660 !args[4]->IsNumber()) {
661 args.GetReturnValue().Set(false);
662 return;
663 }
664
665 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
666 new SyntheticPinchGestureParams);
667
668 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
669 float page_scale_factor = context.web_view()->pageScaleFactor();
670
671 gesture_params->scale_factor = args[0]->NumberValue();
672 gesture_params->anchor.SetPoint(
673 args[1]->IntegerValue() * page_scale_factor,
674 args[2]->IntegerValue() * page_scale_factor);
675 gesture_params->relative_pointer_speed_in_pixels_s =
676 args[4]->IntegerValue();
677
678 v8::Local<v8::Function> callback_local =
679 v8::Local<v8::Function>::Cast(args[3]);
680
681 scoped_refptr<CallbackAndContext> callback_and_context =
682 new CallbackAndContext(args.GetIsolate(),
683 callback_local,
684 context.web_frame()->mainWorldScriptContext());
685
686
687 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
688 // progress, we will leak the callback and context. This needs to be fixed,
689 // somehow.
690 context.render_view_impl()->QueueSyntheticGesture(
691 gesture_params.Pass(),
692 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
693
694 args.GetReturnValue().Set(true);
695 }
696
697 static void BeginTap(
698 const v8::FunctionCallbackInfo<v8::Value>& args) {
699 GpuBenchmarkingContext context;
700 if (!context.Init(false))
701 return;
702
703 int arglen = args.Length();
704 if (arglen < 5 ||
705 !args[0]->IsNumber() ||
706 !args[1]->IsNumber() ||
707 !args[2]->IsFunction() ||
708 !args[3]->IsNumber() ||
709 !args[4]->IsNumber()) {
710 args.GetReturnValue().Set(false);
711 return;
712 }
713
714 scoped_ptr<SyntheticTapGestureParams> gesture_params(
715 new SyntheticTapGestureParams);
716
717 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
718 float page_scale_factor = context.web_view()->pageScaleFactor();
719
720 gesture_params->position.SetPoint(
721 args[0]->IntegerValue() * page_scale_factor,
722 args[1]->IntegerValue() * page_scale_factor);
723 gesture_params->duration_ms = args[3]->IntegerValue();
724
725 int gesture_source_type = args[4]->IntegerValue();
726 if (gesture_source_type < 0 ||
727 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
728 args.GetReturnValue().Set(false);
729 return;
730 }
731 gesture_params->gesture_source_type =
732 static_cast<SyntheticGestureParams::GestureSourceType>(
733 gesture_source_type);
734
735 v8::Local<v8::Function> callback_local =
736 v8::Local<v8::Function>::Cast(args[2]);
737
738 scoped_refptr<CallbackAndContext> callback_and_context =
739 new CallbackAndContext(args.GetIsolate(),
740 callback_local,
741 context.web_frame()->mainWorldScriptContext());
742
743
744 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
745 // progress, we will leak the callback and context. This needs to be fixed,
746 // somehow.
747 context.render_view_impl()->QueueSyntheticGesture(
748 gesture_params.Pass(),
749 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
750
751 args.GetReturnValue().Set(true);
752 }
753
754 static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
755 const gfx::Size& size,
756 const std::vector<unsigned char>& png) {
757 v8::Isolate* isolate = callback_and_context->isolate();
758 v8::HandleScope scope(isolate);
759 v8::Handle<v8::Context> context = callback_and_context->GetContext();
760 v8::Context::Scope context_scope(context);
761 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
762 if (frame) {
763
764 v8::Handle<v8::Value> result;
765
766 if(!size.IsEmpty()) {
767 v8::Handle<v8::Object> result_object;
768 result_object = v8::Object::New(isolate);
769
770 result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
771 v8::Number::New(isolate, size.width()));
772 result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
773 v8::Number::New(isolate, size.height()));
774
775 std::string base64_png;
776 base::Base64Encode(base::StringPiece(
777 reinterpret_cast<const char*>(&*png.begin()), png.size()),
778 &base64_png);
779
780 result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
781 v8::String::NewFromUtf8(isolate,
782 base64_png.c_str(),
783 v8::String::kNormalString,
784 base64_png.size()));
785
786 result = result_object;
787 } else {
788 result = v8::Null(isolate);
789 }
790
791 v8::Handle<v8::Value> argv[] = { result };
792
793 frame->callFunctionEvenIfScriptDisabled(
794 callback_and_context->GetCallback(),
795 v8::Object::New(isolate),
796 1,
797 argv);
798 }
799 }
800
801 static void BeginWindowSnapshotPNG(
802 const v8::FunctionCallbackInfo<v8::Value>& args) {
803 GpuBenchmarkingContext context;
804 if (!context.Init(false))
805 return;
806
807 if (!args[0]->IsFunction())
808 return;
809
810 v8::Local<v8::Function> callback_local =
811 v8::Local<v8::Function>::Cast(args[0]);
812
813 scoped_refptr<CallbackAndContext> callback_and_context =
814 new CallbackAndContext(args.GetIsolate(),
815 callback_local,
816 context.web_frame()->mainWorldScriptContext());
817
818 context.render_view_impl()->GetWindowSnapshot(
819 base::Bind(&OnSnapshotCompleted, callback_and_context));
820 }
821
822 static void ClearImageCache(
823 const v8::FunctionCallbackInfo<v8::Value>& args) {
824 WebImageCache::clear();
825 }
826
827 static void OnMicroBenchmarkCompleted(
828 CallbackAndContext* callback_and_context,
829 scoped_ptr<base::Value> result) {
830 v8::Isolate* isolate = callback_and_context->isolate();
831 v8::HandleScope scope(isolate);
832 v8::Handle<v8::Context> context = callback_and_context->GetContext();
833 v8::Context::Scope context_scope(context);
834 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
835 if (frame) {
836 scoped_ptr<V8ValueConverter> converter =
837 make_scoped_ptr(V8ValueConverter::create());
838 v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
839 v8::Handle<v8::Value> argv[] = { value };
840
841 frame->callFunctionEvenIfScriptDisabled(
842 callback_and_context->GetCallback(),
843 v8::Object::New(isolate),
844 1,
845 argv);
846 }
847 }
848
849 static void RunMicroBenchmark(
850 const v8::FunctionCallbackInfo<v8::Value>& args) {
851 GpuBenchmarkingContext context;
852 if (!context.Init(true)) {
853 args.GetReturnValue().Set(0);
854 return;
855 }
856
857 if (args.Length() != 3 ||
858 !args[0]->IsString() ||
859 !args[1]->IsFunction() ||
860 !args[2]->IsObject()) {
861 args.GetReturnValue().Set(0);
862 return;
863 }
864
865 v8::Local<v8::Function> callback_local =
866 v8::Local<v8::Function>::Cast(args[1]);
867
868 scoped_refptr<CallbackAndContext> callback_and_context =
869 new CallbackAndContext(args.GetIsolate(),
870 callback_local,
871 context.web_frame()->mainWorldScriptContext());
872
873 scoped_ptr<V8ValueConverter> converter = 247 scoped_ptr<V8ValueConverter> converter =
874 make_scoped_ptr(V8ValueConverter::create()); 248 make_scoped_ptr(V8ValueConverter::create());
875 v8::Handle<v8::Context> v8_context = callback_and_context->GetContext(); 249 v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
876 scoped_ptr<base::Value> value = 250 v8::Handle<v8::Value> argv[] = { value };
877 make_scoped_ptr(converter->FromV8Value(args[2], v8_context)); 251
878 252 frame->callFunctionEvenIfScriptDisabled(
879 v8::String::Utf8Value benchmark(args[0]); 253 callback_and_context->GetCallback(),
880 DCHECK(*benchmark); 254 v8::Object::New(isolate),
881 args.GetReturnValue().Set(context.compositor()->ScheduleMicroBenchmark( 255 1,
882 std::string(*benchmark), 256 argv);
883 value.Pass(), 257 }
884 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context))); 258 }
885 } 259
886 260 void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
887 static void SendMessageToMicroBenchmark( 261 const gfx::Size& size,
888 const v8::FunctionCallbackInfo<v8::Value>& args) { 262 const std::vector<unsigned char>& png) {
889 GpuBenchmarkingContext context; 263 v8::Isolate* isolate = callback_and_context->isolate();
890 if (!context.Init(true)) { 264 v8::HandleScope scope(isolate);
891 args.GetReturnValue().Set(0); 265 v8::Handle<v8::Context> context = callback_and_context->GetContext();
892 return; 266 v8::Context::Scope context_scope(context);
267 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
268 if (frame) {
269 v8::Handle<v8::Value> result;
270
271 if (!size.IsEmpty()) {
272 v8::Handle<v8::Object> result_object;
273 result_object = v8::Object::New(isolate);
274
275 result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
276 v8::Number::New(isolate, size.width()));
277 result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
278 v8::Number::New(isolate, size.height()));
279
280 std::string base64_png;
281 base::Base64Encode(
282 base::StringPiece(reinterpret_cast<const char*>(&*png.begin()),
283 png.size()),
284 &base64_png);
285
286 result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
287 v8::String::NewFromUtf8(isolate,
288 base64_png.c_str(),
289 v8::String::kNormalString,
290 base64_png.size()));
291
292 result = result_object;
293 } else {
294 result = v8::Null(isolate);
893 } 295 }
894 296
895 if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsObject()) { 297 v8::Handle<v8::Value> argv[] = {result};
896 args.GetReturnValue().Set(0); 298
897 return; 299 frame->callFunctionEvenIfScriptDisabled(
898 } 300 callback_and_context->GetCallback(), v8::Object::New(isolate), 1, argv);
899 301 }
900 scoped_ptr<V8ValueConverter> converter = 302 }
901 make_scoped_ptr(V8ValueConverter::create()); 303
902 v8::Handle<v8::Context> v8_context = 304 void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
903 context.web_frame()->mainWorldScriptContext(); 305 v8::Isolate* isolate = callback_and_context->isolate();
904 scoped_ptr<base::Value> value = 306 v8::HandleScope scope(isolate);
905 make_scoped_ptr(converter->FromV8Value(args[1], v8_context)); 307 v8::Handle<v8::Context> context = callback_and_context->GetContext();
906 308 v8::Context::Scope context_scope(context);
907 int id = 0; 309 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
908 converter->FromV8Value(args[0], v8_context)->GetAsInteger(&id); 310 if (frame) {
909 args.GetReturnValue().Set( 311 frame->callFunctionEvenIfScriptDisabled(
910 context.compositor()->SendMessageToMicroBenchmark(id, value.Pass())); 312 callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
911 } 313 }
912 314 }
913 static void HasGpuProcess(const v8::FunctionCallbackInfo<v8::Value>& args) { 315
316 bool BeginSmoothScroll(v8::Isolate* isolate,
317 int pixels_to_scroll,
318 v8::Handle<v8::Function> callback,
319 int gesture_source_type,
320 const std::string& direction,
321 int speed_in_pixels_s,
322 bool prevent_fling,
323 int start_x,
324 int start_y) {
325 GpuBenchmarkingContext context;
326 if (!context.Init(false))
327 return false;
328
329 scoped_refptr<CallbackAndContext> callback_and_context =
330 new CallbackAndContext(
331 isolate, callback, context.web_frame()->mainWorldScriptContext());
332
333 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
334 new SyntheticSmoothScrollGestureParams);
335
336 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
337 float page_scale_factor = context.web_view()->pageScaleFactor();
338
339 if (gesture_source_type < 0 ||
340 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
341 return false;
342 }
343 gesture_params->gesture_source_type =
344 static_cast<SyntheticGestureParams::GestureSourceType>(
345 gesture_source_type);
346
347 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
348 gesture_params->prevent_fling = prevent_fling;
349
350 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
351 start_y * page_scale_factor);
352
353 int distance_length = pixels_to_scroll * page_scale_factor;
354 gfx::Vector2d distance;
355 if (direction == "down")
356 distance.set_y(-distance_length);
357 else if (direction == "up")
358 distance.set_y(distance_length);
359 else if (direction == "right")
360 distance.set_x(-distance_length);
361 else if (direction == "left")
362 distance.set_x(distance_length);
363 else {
364 return false;
365 }
366 gesture_params->distances.push_back(distance);
367
368 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
369 // progress, we will leak the callback and context. This needs to be fixed,
370 // somehow.
371 context.render_view_impl()->QueueSyntheticGesture(
372 gesture_params.Pass(),
373 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
374
375 return true;
376 }
377
378 } // namespace
379
380 gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
381
382 // static
383 void GpuBenchmarking::Install(blink::WebFrame* frame) {
384 v8::Isolate* isolate = blink::mainThreadIsolate();
385 v8::HandleScope handle_scope(isolate);
386 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
387 if (context.IsEmpty())
388 return;
389
390 v8::Context::Scope context_scope(context);
391
392 gin::Handle<GpuBenchmarking> controller =
393 gin::CreateHandle(isolate, new GpuBenchmarking());
394 if (controller.IsEmpty())
395 return;
396
397 v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
398 context->Global());
399 chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
400 }
401
402 GpuBenchmarking::GpuBenchmarking() {
403 }
404
405 GpuBenchmarking::~GpuBenchmarking() {
406 }
407
408 gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
409 v8::Isolate* isolate) {
410 return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
411 .SetMethod("setNeedsDisplayOnAllLayers",
412 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
413 .SetMethod("setRasterizeOnlyVisibleContent",
414 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
415 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
416 .SetValue("DEFAULT_INPUT", 0)
417 .SetValue("TOUCH_INPUT", 1)
418 .SetValue("MOUSE_INPUT", 2)
419 .SetMethod("gestureSourceTypeSupported",
420 &GpuBenchmarking::GestureSourceTypeSupported)
421 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
422 .SetMethod("swipe", &GpuBenchmarking::Swipe)
423 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
424 // TODO(dominikg): Remove once JS interface changes have rolled into
425 // stable.
426 .SetValue("newPinchInterface", true)
427 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
428 .SetMethod("tap", &GpuBenchmarking::Tap)
429 .SetMethod("beginWindowSnapshotPNG",
430 &GpuBenchmarking::BeginWindowSnapshotPNG)
431 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
432 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
433 .SetMethod("sendMessageToMicroBenchmark",
434 &GpuBenchmarking::SendMessageToMicroBenchmark)
435 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
436 }
437
438 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
439 GpuBenchmarkingContext context;
440 if (!context.Init(true))
441 return;
442
443 context.compositor()->SetNeedsDisplayOnAllLayers();
444 }
445
446 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
447 GpuBenchmarkingContext context;
448 if (!context.Init(true))
449 return;
450
451 context.compositor()->SetRasterizeOnlyVisibleContent();
452 }
453
454 void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
455 const std::string& dirname) {
456 GpuBenchmarkingContext context;
457 if (!context.Init(true))
458 return;
459
460 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
461 if (!root_layer)
462 return;
463
464 base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
465 if (!base::CreateDirectory(dirpath) ||
466 !base::PathIsWritable(dirpath)) {
467 std::string msg("Path is not writable: ");
468 msg.append(dirpath.MaybeAsASCII());
469 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
470 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
471 return;
472 }
473
474 SkPictureSerializer serializer(dirpath);
475 serializer.Serialize(root_layer);
476 }
477
478 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
479 if (gesture_source_type < 0 ||
480 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
481 return false;
482 }
483
484 return SyntheticGestureParams::IsGestureSourceTypeSupported(
485 static_cast<SyntheticGestureParams::GestureSourceType>(
486 gesture_source_type));
487 }
488
489 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
490 GpuBenchmarkingContext context;
491 if (!context.Init(true))
492 return false;
493
494 float page_scale_factor = context.web_view()->pageScaleFactor();
495 blink::WebRect rect = context.render_view_impl()->windowRect();
496
497 int pixels_to_scroll = 0;
498 v8::Handle<v8::Function> callback;
499 int start_x = rect.width / (page_scale_factor * 2);
500 int start_y = rect.height / (page_scale_factor * 2);
501 int gesture_source_type = 0; // DEFAULT_INPUT
502 std::string direction = "down";
503 int speed_in_pixels_s = 800;
504
505 if (!GetOptionalArg(args, &pixels_to_scroll) ||
506 !GetOptionalArg(args, &callback) ||
507 !GetOptionalArg(args, &start_x) ||
508 !GetOptionalArg(args, &start_y) ||
509 !GetOptionalArg(args, &gesture_source_type) ||
510 !GetOptionalArg(args, &direction) ||
511 !GetOptionalArg(args, &speed_in_pixels_s)) {
512 return false;
513 }
514
515 return BeginSmoothScroll(args->isolate(),
516 pixels_to_scroll,
517 callback,
518 gesture_source_type,
519 direction,
520 speed_in_pixels_s,
521 true,
522 start_x,
523 start_y);
524 }
525
526 bool GpuBenchmarking::Swipe(gin::Arguments* args) {
527 GpuBenchmarkingContext context;
528 if (!context.Init(true))
529 return false;
530
531 float page_scale_factor = context.web_view()->pageScaleFactor();
532 blink::WebRect rect = context.render_view_impl()->windowRect();
533
534 std::string direction = "up";
535 int pixels_to_scroll = 0;
536 v8::Handle<v8::Function> callback;
537 int start_x = rect.width / (page_scale_factor * 2);
538 int start_y = rect.height / (page_scale_factor * 2);
539 int speed_in_pixels_s = 800;
540
541 if (!GetOptionalArg(args, &direction) ||
542 !GetOptionalArg(args, &pixels_to_scroll) ||
543 !GetOptionalArg(args, &callback) ||
544 !GetOptionalArg(args, &start_x) ||
545 !GetOptionalArg(args, &start_y) ||
546 !GetOptionalArg(args, &speed_in_pixels_s)) {
547 return false;
548 }
549
550 return BeginSmoothScroll(args->isolate(),
551 -pixels_to_scroll,
552 callback,
553 1, // TOUCH_INPUT
554 direction,
555 speed_in_pixels_s,
556 false,
557 start_x,
558 start_y);
559 }
560
561 bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
562 GpuBenchmarkingContext context;
563 if (!context.Init(false))
564 return false;
565
566 float page_scale_factor = context.web_view()->pageScaleFactor();
567 blink::WebRect rect = context.render_view_impl()->windowRect();
568
569 std::string direction = "down";
570 int distance_length = 0;
571 int overscroll_length = 0;
572 int repeat_count = 1;
573 v8::Handle<v8::Function> callback;
574 int start_x = rect.width / (page_scale_factor * 2);
575 int start_y = rect.height / (page_scale_factor * 2);
576 int speed_in_pixels_s = 800;
577
578 if (!GetOptionalArg(args, &direction) ||
579 !GetOptionalArg(args, &distance_length) ||
580 !GetOptionalArg(args, &overscroll_length) ||
581 !GetOptionalArg(args, &repeat_count) ||
582 !GetOptionalArg(args, &callback) ||
583 !GetOptionalArg(args, &start_x) ||
584 !GetOptionalArg(args, &start_y) ||
585 !GetOptionalArg(args, &speed_in_pixels_s)) {
586 return false;
587 }
588
589 scoped_refptr<CallbackAndContext> callback_and_context =
590 new CallbackAndContext(args->isolate(),
591 callback,
592 context.web_frame()->mainWorldScriptContext());
593
594 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
595 new SyntheticSmoothScrollGestureParams);
596
597 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
598
599 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
600 start_y * page_scale_factor);
601
602 distance_length *= page_scale_factor;
603 overscroll_length *= page_scale_factor;
604 gfx::Vector2d distance;
605 gfx::Vector2d overscroll;
606 if (direction == "down") {
607 distance.set_y(-distance_length);
608 overscroll.set_y(overscroll_length);
609 } else if (direction == "up") {
610 distance.set_y(distance_length);
611 overscroll.set_y(-overscroll_length);
612 } else if (direction == "right") {
613 distance.set_x(-distance_length);
614 overscroll.set_x(overscroll_length);
615 } else if (direction == "left") {
616 distance.set_x(distance_length);
617 overscroll.set_x(-overscroll_length);
618 } else {
619 return false;
620 }
621
622 for (int i = 0; i < repeat_count; i++) {
623 gesture_params->distances.push_back(distance);
624 gesture_params->distances.push_back(-distance + overscroll);
625 }
626
627 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
628 // progress, we will leak the callback and context. This needs to be fixed,
629 // somehow.
630 context.render_view_impl()->QueueSyntheticGesture(
631 gesture_params.Pass(),
632 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
633
634 return true;
635 }
636
637 bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
638 GpuBenchmarkingContext context;
639 if (!context.Init(false))
640 return false;
641
642 float scale_factor;
643 int anchor_x;
644 int anchor_y;
645 v8::Handle<v8::Function> callback;
646 int relative_pointer_speed_in_pixels_s = 800;
647
648
649 if (!GetArg(args, &scale_factor) ||
650 !GetArg(args, &anchor_x) ||
651 !GetArg(args, &anchor_y) ||
652 !GetOptionalArg(args, &callback) ||
653 !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
654 return false;
655 }
656
657 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
658 new SyntheticPinchGestureParams);
659
660 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
661 float page_scale_factor = context.web_view()->pageScaleFactor();
662
663 gesture_params->scale_factor = scale_factor;
664 gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
665 anchor_y * page_scale_factor);
666 gesture_params->relative_pointer_speed_in_pixels_s =
667 relative_pointer_speed_in_pixels_s;
668
669 scoped_refptr<CallbackAndContext> callback_and_context =
670 new CallbackAndContext(args->isolate(),
671 callback,
672 context.web_frame()->mainWorldScriptContext());
673
674
675 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
676 // progress, we will leak the callback and context. This needs to be fixed,
677 // somehow.
678 context.render_view_impl()->QueueSyntheticGesture(
679 gesture_params.Pass(),
680 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
681
682 return true;
683 }
684
685 bool GpuBenchmarking::Tap(gin::Arguments* args) {
686 GpuBenchmarkingContext context;
687 if (!context.Init(false))
688 return false;
689
690 int position_x;
691 int position_y;
692 v8::Handle<v8::Function> callback;
693 int duration_ms = 50;
694 int gesture_source_type = 0; // DEFAULT_INPUT
695
696 if (!GetArg(args, &position_x) ||
697 !GetArg(args, &position_y) ||
698 !GetOptionalArg(args, &callback) ||
699 !GetOptionalArg(args, &duration_ms) ||
700 !GetOptionalArg(args, &gesture_source_type)) {
701 return false;
702 }
703
704 scoped_ptr<SyntheticTapGestureParams> gesture_params(
705 new SyntheticTapGestureParams);
706
707 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
708 float page_scale_factor = context.web_view()->pageScaleFactor();
709
710 gesture_params->position.SetPoint(position_x * page_scale_factor,
711 position_y * page_scale_factor);
712 gesture_params->duration_ms = duration_ms;
713
714 if (gesture_source_type < 0 ||
715 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
716 return false;
717 }
718 gesture_params->gesture_source_type =
719 static_cast<SyntheticGestureParams::GestureSourceType>(
720 gesture_source_type);
721
722 scoped_refptr<CallbackAndContext> callback_and_context =
723 new CallbackAndContext(args->isolate(),
724 callback,
725 context.web_frame()->mainWorldScriptContext());
726
727 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
728 // progress, we will leak the callback and context. This needs to be fixed,
729 // somehow.
730 context.render_view_impl()->QueueSyntheticGesture(
731 gesture_params.Pass(),
732 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
733
734 return true;
735 }
736
737 void GpuBenchmarking::BeginWindowSnapshotPNG(
738 v8::Isolate* isolate,
739 v8::Handle<v8::Function> callback) {
740 GpuBenchmarkingContext context;
741 if (!context.Init(false))
742 return;
743
744 scoped_refptr<CallbackAndContext> callback_and_context =
745 new CallbackAndContext(isolate,
746 callback,
747 context.web_frame()->mainWorldScriptContext());
748
749 context.render_view_impl()->GetWindowSnapshot(
750 base::Bind(&OnSnapshotCompleted, callback_and_context));
751 }
752
753 void GpuBenchmarking::ClearImageCache() {
754 WebImageCache::clear();
755 }
756
757 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
758 GpuBenchmarkingContext context;
759 if (!context.Init(true))
760 return 0;
761
762 std::string name;
763 v8::Handle<v8::Function> callback;
764 v8::Handle<v8::Object> arguments;
765
766 if (!GetArg(args, &name) || !GetArg(args, &callback) ||
767 !GetOptionalArg(args, &arguments)) {
768 return 0;
769 }
770
771 scoped_refptr<CallbackAndContext> callback_and_context =
772 new CallbackAndContext(args->isolate(),
773 callback,
774 context.web_frame()->mainWorldScriptContext());
775
776 scoped_ptr<V8ValueConverter> converter =
777 make_scoped_ptr(V8ValueConverter::create());
778 v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
779 scoped_ptr<base::Value> value =
780 make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
781
782 return context.compositor()->ScheduleMicroBenchmark(
783 name,
784 value.Pass(),
785 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
786 }
787
788 bool GpuBenchmarking::SendMessageToMicroBenchmark(
789 int id,
790 v8::Handle<v8::Object> message) {
791 GpuBenchmarkingContext context;
792 if (!context.Init(true))
793 return false;
794
795 scoped_ptr<V8ValueConverter> converter =
796 make_scoped_ptr(V8ValueConverter::create());
797 v8::Handle<v8::Context> v8_context =
798 context.web_frame()->mainWorldScriptContext();
799 scoped_ptr<base::Value> value =
800 make_scoped_ptr(converter->FromV8Value(message, v8_context));
801
802 return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
803 }
804
805 bool GpuBenchmarking::HasGpuProcess() {
914 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel(); 806 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
915 args.GetReturnValue().Set(!!gpu_channel); 807 return !!gpu_channel;
916 }
917 };
918
919 v8::Extension* GpuBenchmarkingExtension::Get() {
920 return new GpuBenchmarkingWrapper();
921 } 808 }
922 809
923 } // namespace content 810 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/gpu/gpu_benchmarking_extension.h ('k') | content/renderer/render_thread_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698