third_party/re2: Remove remove-static-initializers.patch.
[chromium-blink-merge.git] / content / renderer / gpu / gpu_benchmarking_extension.cc
blobd4890b5af6147436d3fea6a3ccf81244b8a03f89
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
3 // found in the LICENSE file.
5 #include "content/renderer/gpu/gpu_benchmarking_extension.h"
7 #include <string>
9 #include "base/base64.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "cc/layers/layer.h"
15 #include "content/common/input/synthetic_gesture_params.h"
16 #include "content/common/input/synthetic_pinch_gesture_params.h"
17 #include "content/common/input/synthetic_smooth_drag_gesture_params.h"
18 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
19 #include "content/common/input/synthetic_tap_gesture_params.h"
20 #include "content/public/child/v8_value_converter.h"
21 #include "content/public/renderer/render_thread.h"
22 #include "content/renderer/chrome_object_extensions_utils.h"
23 #include "content/renderer/gpu/render_widget_compositor.h"
24 #include "content/renderer/render_thread_impl.h"
25 #include "content/renderer/render_view_impl.h"
26 #include "content/renderer/skia_benchmarking_extension.h"
27 #include "gin/arguments.h"
28 #include "gin/handle.h"
29 #include "gin/object_template_builder.h"
30 #include "third_party/WebKit/public/web/WebImageCache.h"
31 #include "third_party/WebKit/public/web/WebKit.h"
32 #include "third_party/WebKit/public/web/WebLocalFrame.h"
33 #include "third_party/WebKit/public/web/WebView.h"
34 #include "third_party/skia/include/core/SkData.h"
35 #include "third_party/skia/include/core/SkGraphics.h"
36 #include "third_party/skia/include/core/SkPicture.h"
37 #include "third_party/skia/include/core/SkPixelRef.h"
38 #include "third_party/skia/include/core/SkPixelSerializer.h"
39 #include "third_party/skia/include/core/SkStream.h"
40 #include "ui/gfx/codec/png_codec.h"
41 #include "v8/include/v8.h"
43 using blink::WebCanvas;
44 using blink::WebLocalFrame;
45 using blink::WebImageCache;
46 using blink::WebPrivatePtr;
47 using blink::WebSize;
48 using blink::WebView;
50 namespace content {
52 namespace {
54 class PNGSerializer : public SkPixelSerializer {
55 protected:
56 bool onUseEncodedData(const void* data, size_t len) override { return true; }
58 SkData* onEncodePixels(const SkImageInfo& info,
59 const void* pixels,
60 size_t row_bytes) override {
61 SkBitmap bm;
62 // The const_cast is fine, since we only read from the bitmap.
63 if (bm.installPixels(info, const_cast<void*>(pixels), row_bytes)) {
64 std::vector<unsigned char> vector;
65 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
66 return SkData::NewWithCopy(&vector.front(), vector.size());
69 return nullptr;
73 class SkPictureSerializer {
74 public:
75 explicit SkPictureSerializer(const base::FilePath& dirpath)
76 : dirpath_(dirpath),
77 layer_id_(0) {
78 // Let skia register known effect subclasses. This basically enables
79 // reflection on those subclasses required for picture serialization.
80 SkiaBenchmarking::Initialize();
83 // Recursively serializes the layer tree.
84 // Each layer in the tree is serialized into a separate skp file
85 // in the given directory.
86 void Serialize(const cc::Layer* layer) {
87 const cc::LayerList& children = layer->children();
88 for (size_t i = 0; i < children.size(); ++i) {
89 Serialize(children[i].get());
92 skia::RefPtr<SkPicture> picture = layer->GetPicture();
93 if (!picture)
94 return;
96 // Serialize picture to file.
97 // TODO(alokp): Note that for this to work Chrome needs to be launched with
98 // --no-sandbox command-line flag. Get rid of this limitation.
99 // CRBUG: 139640.
100 std::string filename = "layer_" + base::IntToString(layer_id_++) + ".skp";
101 std::string filepath = dirpath_.AppendASCII(filename).MaybeAsASCII();
102 DCHECK(!filepath.empty());
103 SkFILEWStream file(filepath.c_str());
104 DCHECK(file.isValid());
106 PNGSerializer serializer;
107 picture->serialize(&file, &serializer);
110 private:
111 base::FilePath dirpath_;
112 int layer_id_;
115 template <typename T>
116 bool GetArg(gin::Arguments* args, T* value) {
117 if (!args->GetNext(value)) {
118 args->ThrowError();
119 return false;
121 return true;
124 template <>
125 bool GetArg(gin::Arguments* args, int* value) {
126 float number;
127 bool ret = GetArg(args, &number);
128 *value = number;
129 return ret;
132 template <typename T>
133 bool GetOptionalArg(gin::Arguments* args, T* value) {
134 if (args->PeekNext().IsEmpty())
135 return true;
136 if (args->PeekNext()->IsUndefined()) {
137 args->Skip();
138 return true;
140 return GetArg(args, value);
143 class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
144 public:
145 CallbackAndContext(v8::Isolate* isolate,
146 v8::Handle<v8::Function> callback,
147 v8::Handle<v8::Context> context)
148 : isolate_(isolate) {
149 callback_.Reset(isolate_, callback);
150 context_.Reset(isolate_, context);
153 v8::Isolate* isolate() {
154 return isolate_;
157 v8::Handle<v8::Function> GetCallback() {
158 return v8::Local<v8::Function>::New(isolate_, callback_);
161 v8::Handle<v8::Context> GetContext() {
162 return v8::Local<v8::Context>::New(isolate_, context_);
165 private:
166 friend class base::RefCounted<CallbackAndContext>;
168 virtual ~CallbackAndContext() {
169 callback_.Reset();
170 context_.Reset();
173 v8::Isolate* isolate_;
174 v8::Persistent<v8::Function> callback_;
175 v8::Persistent<v8::Context> context_;
176 DISALLOW_COPY_AND_ASSIGN(CallbackAndContext);
179 class GpuBenchmarkingContext {
180 public:
181 GpuBenchmarkingContext()
182 : web_frame_(NULL),
183 web_view_(NULL),
184 render_view_impl_(NULL),
185 compositor_(NULL) {}
187 bool Init(bool init_compositor) {
188 web_frame_ = WebLocalFrame::frameForCurrentContext();
189 if (!web_frame_)
190 return false;
192 web_view_ = web_frame_->view();
193 if (!web_view_) {
194 web_frame_ = NULL;
195 return false;
198 render_view_impl_ = RenderViewImpl::FromWebView(web_view_);
199 if (!render_view_impl_) {
200 web_frame_ = NULL;
201 web_view_ = NULL;
202 return false;
205 if (!init_compositor)
206 return true;
208 compositor_ = render_view_impl_->compositor();
209 if (!compositor_) {
210 web_frame_ = NULL;
211 web_view_ = NULL;
212 render_view_impl_ = NULL;
213 return false;
216 return true;
219 WebLocalFrame* web_frame() const {
220 DCHECK(web_frame_ != NULL);
221 return web_frame_;
223 WebView* web_view() const {
224 DCHECK(web_view_ != NULL);
225 return web_view_;
227 RenderViewImpl* render_view_impl() const {
228 DCHECK(render_view_impl_ != NULL);
229 return render_view_impl_;
231 RenderWidgetCompositor* compositor() const {
232 DCHECK(compositor_ != NULL);
233 return compositor_;
236 private:
237 WebLocalFrame* web_frame_;
238 WebView* web_view_;
239 RenderViewImpl* render_view_impl_;
240 RenderWidgetCompositor* compositor_;
242 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
245 void OnMicroBenchmarkCompleted(
246 CallbackAndContext* callback_and_context,
247 scoped_ptr<base::Value> result) {
248 v8::Isolate* isolate = callback_and_context->isolate();
249 v8::HandleScope scope(isolate);
250 v8::Handle<v8::Context> context = callback_and_context->GetContext();
251 v8::Context::Scope context_scope(context);
252 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
253 if (frame) {
254 scoped_ptr<V8ValueConverter> converter =
255 make_scoped_ptr(V8ValueConverter::create());
256 v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
257 #ifdef WEB_FRAME_USES_V8_LOCAL
258 v8::Local<v8::Value> argv[] = {value};
259 #else
260 v8::Handle<v8::Value> argv[] = { value };
261 #endif
262 frame->callFunctionEvenIfScriptDisabled(
263 callback_and_context->GetCallback(),
264 v8::Object::New(isolate),
266 argv);
270 void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
271 v8::Isolate* isolate = callback_and_context->isolate();
272 v8::HandleScope scope(isolate);
273 v8::Handle<v8::Context> context = callback_and_context->GetContext();
274 v8::Context::Scope context_scope(context);
275 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
276 if (frame) {
277 frame->callFunctionEvenIfScriptDisabled(
278 callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
282 bool BeginSmoothScroll(v8::Isolate* isolate,
283 float pixels_to_scroll,
284 v8::Handle<v8::Function> callback,
285 int gesture_source_type,
286 const std::string& direction,
287 float speed_in_pixels_s,
288 bool prevent_fling,
289 float start_x,
290 float start_y) {
291 GpuBenchmarkingContext context;
292 if (!context.Init(false))
293 return false;
295 scoped_refptr<CallbackAndContext> callback_and_context =
296 new CallbackAndContext(
297 isolate, callback, context.web_frame()->mainWorldScriptContext());
299 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
300 new SyntheticSmoothScrollGestureParams);
302 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
303 float page_scale_factor = context.web_view()->pageScaleFactor();
305 if (gesture_source_type < 0 ||
306 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
307 return false;
309 gesture_params->gesture_source_type =
310 static_cast<SyntheticGestureParams::GestureSourceType>(
311 gesture_source_type);
313 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
314 gesture_params->prevent_fling = prevent_fling;
316 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
317 start_y * page_scale_factor);
319 float distance_length = pixels_to_scroll * page_scale_factor;
320 gfx::Vector2dF distance;
321 if (direction == "down")
322 distance.set_y(-distance_length);
323 else if (direction == "up")
324 distance.set_y(distance_length);
325 else if (direction == "right")
326 distance.set_x(-distance_length);
327 else if (direction == "left")
328 distance.set_x(distance_length);
329 else if (direction == "upleft") {
330 distance.set_y(distance_length);
331 distance.set_x(distance_length);
332 } else if (direction == "upright") {
333 distance.set_y(distance_length);
334 distance.set_x(-distance_length);
335 } else if (direction == "downleft") {
336 distance.set_y(-distance_length);
337 distance.set_x(distance_length);
338 } else if (direction == "downright") {
339 distance.set_y(-distance_length);
340 distance.set_x(-distance_length);
341 } else {
342 return false;
344 gesture_params->distances.push_back(distance);
346 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
347 // progress, we will leak the callback and context. This needs to be fixed,
348 // somehow.
349 context.render_view_impl()->QueueSyntheticGesture(
350 gesture_params.Pass(),
351 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
353 return true;
356 bool BeginSmoothDrag(v8::Isolate* isolate,
357 float start_x,
358 float start_y,
359 float end_x,
360 float end_y,
361 v8::Handle<v8::Function> callback,
362 int gesture_source_type,
363 float speed_in_pixels_s) {
364 GpuBenchmarkingContext context;
365 if (!context.Init(false))
366 return false;
367 scoped_refptr<CallbackAndContext> callback_and_context =
368 new CallbackAndContext(isolate, callback,
369 context.web_frame()->mainWorldScriptContext());
371 scoped_ptr<SyntheticSmoothDragGestureParams> gesture_params(
372 new SyntheticSmoothDragGestureParams);
374 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
375 float page_scale_factor = context.web_view()->pageScaleFactor();
377 gesture_params->start_point.SetPoint(start_x * page_scale_factor,
378 start_y * page_scale_factor);
379 gfx::PointF end_point(end_x * page_scale_factor,
380 end_y * page_scale_factor);
381 gfx::Vector2dF distance = end_point - gesture_params->start_point;
382 gesture_params->distances.push_back(distance);
383 gesture_params->speed_in_pixels_s = speed_in_pixels_s * page_scale_factor;
384 gesture_params->gesture_source_type =
385 static_cast<SyntheticGestureParams::GestureSourceType>(
386 gesture_source_type);
388 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
389 // progress, we will leak the callback and context. This needs to be fixed,
390 // somehow.
391 context.render_view_impl()->QueueSyntheticGesture(
392 gesture_params.Pass(),
393 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
395 return true;
398 } // namespace
400 gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
402 // static
403 void GpuBenchmarking::Install(blink::WebFrame* frame) {
404 v8::Isolate* isolate = blink::mainThreadIsolate();
405 v8::HandleScope handle_scope(isolate);
406 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
407 if (context.IsEmpty())
408 return;
410 v8::Context::Scope context_scope(context);
412 gin::Handle<GpuBenchmarking> controller =
413 gin::CreateHandle(isolate, new GpuBenchmarking());
414 if (controller.IsEmpty())
415 return;
417 v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
418 context->Global());
419 chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
422 GpuBenchmarking::GpuBenchmarking() {
425 GpuBenchmarking::~GpuBenchmarking() {
428 gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
429 v8::Isolate* isolate) {
430 return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
431 .SetMethod("setNeedsDisplayOnAllLayers",
432 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
433 .SetMethod("setRasterizeOnlyVisibleContent",
434 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
435 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
436 .SetValue("DEFAULT_INPUT", 0)
437 .SetValue("TOUCH_INPUT", 1)
438 .SetValue("MOUSE_INPUT", 2)
439 .SetMethod("gestureSourceTypeSupported",
440 &GpuBenchmarking::GestureSourceTypeSupported)
441 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
442 .SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag)
443 .SetMethod("swipe", &GpuBenchmarking::Swipe)
444 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
445 // TODO(dominikg): Remove once JS interface changes have rolled into
446 // stable.
447 .SetValue("newPinchInterface", true)
448 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
449 .SetMethod("tap", &GpuBenchmarking::Tap)
450 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
451 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
452 .SetMethod("sendMessageToMicroBenchmark",
453 &GpuBenchmarking::SendMessageToMicroBenchmark)
454 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
457 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
458 GpuBenchmarkingContext context;
459 if (!context.Init(true))
460 return;
462 context.compositor()->SetNeedsDisplayOnAllLayers();
465 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
466 GpuBenchmarkingContext context;
467 if (!context.Init(true))
468 return;
470 context.compositor()->SetRasterizeOnlyVisibleContent();
473 void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
474 const std::string& dirname) {
475 GpuBenchmarkingContext context;
476 if (!context.Init(true))
477 return;
479 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
480 if (!root_layer)
481 return;
483 base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
484 if (!base::CreateDirectory(dirpath) ||
485 !base::PathIsWritable(dirpath)) {
486 std::string msg("Path is not writable: ");
487 msg.append(dirpath.MaybeAsASCII());
488 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
489 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
490 return;
493 SkPictureSerializer serializer(dirpath);
494 serializer.Serialize(root_layer);
497 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
498 if (gesture_source_type < 0 ||
499 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
500 return false;
503 return SyntheticGestureParams::IsGestureSourceTypeSupported(
504 static_cast<SyntheticGestureParams::GestureSourceType>(
505 gesture_source_type));
508 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
509 GpuBenchmarkingContext context;
510 if (!context.Init(true))
511 return false;
513 float page_scale_factor = context.web_view()->pageScaleFactor();
514 blink::WebRect rect = context.render_view_impl()->windowRect();
516 float pixels_to_scroll = 0;
517 v8::Handle<v8::Function> callback;
518 float start_x = rect.width / (page_scale_factor * 2);
519 float start_y = rect.height / (page_scale_factor * 2);
520 int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
521 std::string direction = "down";
522 float speed_in_pixels_s = 800;
524 if (!GetOptionalArg(args, &pixels_to_scroll) ||
525 !GetOptionalArg(args, &callback) ||
526 !GetOptionalArg(args, &start_x) ||
527 !GetOptionalArg(args, &start_y) ||
528 !GetOptionalArg(args, &gesture_source_type) ||
529 !GetOptionalArg(args, &direction) ||
530 !GetOptionalArg(args, &speed_in_pixels_s)) {
531 return false;
534 return BeginSmoothScroll(args->isolate(),
535 pixels_to_scroll,
536 callback,
537 gesture_source_type,
538 direction,
539 speed_in_pixels_s,
540 true,
541 start_x,
542 start_y);
545 bool GpuBenchmarking::SmoothDrag(gin::Arguments* args) {
546 GpuBenchmarkingContext context;
547 if (!context.Init(true))
548 return false;
550 float start_x;
551 float start_y;
552 float end_x;
553 float end_y;
554 v8::Handle<v8::Function> callback;
555 int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
556 float speed_in_pixels_s = 800;
558 if (!GetArg(args, &start_x) ||
559 !GetArg(args, &start_y) ||
560 !GetArg(args, &end_x) ||
561 !GetArg(args, &end_y) ||
562 !GetOptionalArg(args, &callback) ||
563 !GetOptionalArg(args, &gesture_source_type) ||
564 !GetOptionalArg(args, &speed_in_pixels_s)) {
565 return false;
568 return BeginSmoothDrag(args->isolate(),
569 start_x,
570 start_y,
571 end_x,
572 end_y,
573 callback,
574 gesture_source_type,
575 speed_in_pixels_s);
578 bool GpuBenchmarking::Swipe(gin::Arguments* args) {
579 GpuBenchmarkingContext context;
580 if (!context.Init(true))
581 return false;
583 float page_scale_factor = context.web_view()->pageScaleFactor();
584 blink::WebRect rect = context.render_view_impl()->windowRect();
586 std::string direction = "up";
587 float pixels_to_scroll = 0;
588 v8::Handle<v8::Function> callback;
589 float start_x = rect.width / (page_scale_factor * 2);
590 float start_y = rect.height / (page_scale_factor * 2);
591 float speed_in_pixels_s = 800;
593 if (!GetOptionalArg(args, &direction) ||
594 !GetOptionalArg(args, &pixels_to_scroll) ||
595 !GetOptionalArg(args, &callback) ||
596 !GetOptionalArg(args, &start_x) ||
597 !GetOptionalArg(args, &start_y) ||
598 !GetOptionalArg(args, &speed_in_pixels_s)) {
599 return false;
602 return BeginSmoothScroll(args->isolate(),
603 -pixels_to_scroll,
604 callback,
605 1, // TOUCH_INPUT
606 direction,
607 speed_in_pixels_s,
608 false,
609 start_x,
610 start_y);
613 bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
614 GpuBenchmarkingContext context;
615 if (!context.Init(false))
616 return false;
618 float page_scale_factor = context.web_view()->pageScaleFactor();
619 blink::WebRect rect = context.render_view_impl()->windowRect();
621 std::string direction = "down";
622 float distance_length = 0;
623 float overscroll_length = 0;
624 int repeat_count = 1;
625 v8::Handle<v8::Function> callback;
626 float start_x = rect.width / (page_scale_factor * 2);
627 float start_y = rect.height / (page_scale_factor * 2);
628 float speed_in_pixels_s = 800;
630 if (!GetOptionalArg(args, &direction) ||
631 !GetOptionalArg(args, &distance_length) ||
632 !GetOptionalArg(args, &overscroll_length) ||
633 !GetOptionalArg(args, &repeat_count) ||
634 !GetOptionalArg(args, &callback) ||
635 !GetOptionalArg(args, &start_x) ||
636 !GetOptionalArg(args, &start_y) ||
637 !GetOptionalArg(args, &speed_in_pixels_s)) {
638 return false;
641 scoped_refptr<CallbackAndContext> callback_and_context =
642 new CallbackAndContext(args->isolate(),
643 callback,
644 context.web_frame()->mainWorldScriptContext());
646 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
647 new SyntheticSmoothScrollGestureParams);
649 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
651 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
652 start_y * page_scale_factor);
654 distance_length *= page_scale_factor;
655 overscroll_length *= page_scale_factor;
656 gfx::Vector2dF distance;
657 gfx::Vector2dF overscroll;
658 if (direction == "down") {
659 distance.set_y(-distance_length);
660 overscroll.set_y(overscroll_length);
661 } else if (direction == "up") {
662 distance.set_y(distance_length);
663 overscroll.set_y(-overscroll_length);
664 } else if (direction == "right") {
665 distance.set_x(-distance_length);
666 overscroll.set_x(overscroll_length);
667 } else if (direction == "left") {
668 distance.set_x(distance_length);
669 overscroll.set_x(-overscroll_length);
670 } else {
671 return false;
674 for (int i = 0; i < repeat_count; i++) {
675 gesture_params->distances.push_back(distance);
676 gesture_params->distances.push_back(-distance + overscroll);
679 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
680 // progress, we will leak the callback and context. This needs to be fixed,
681 // somehow.
682 context.render_view_impl()->QueueSyntheticGesture(
683 gesture_params.Pass(),
684 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
686 return true;
689 bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
690 GpuBenchmarkingContext context;
691 if (!context.Init(false))
692 return false;
694 float scale_factor;
695 float anchor_x;
696 float anchor_y;
697 v8::Handle<v8::Function> callback;
698 float relative_pointer_speed_in_pixels_s = 800;
701 if (!GetArg(args, &scale_factor) ||
702 !GetArg(args, &anchor_x) ||
703 !GetArg(args, &anchor_y) ||
704 !GetOptionalArg(args, &callback) ||
705 !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
706 return false;
709 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
710 new SyntheticPinchGestureParams);
712 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
713 float page_scale_factor = context.web_view()->pageScaleFactor();
715 gesture_params->scale_factor = scale_factor;
716 gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
717 anchor_y * page_scale_factor);
718 gesture_params->relative_pointer_speed_in_pixels_s =
719 relative_pointer_speed_in_pixels_s;
721 scoped_refptr<CallbackAndContext> callback_and_context =
722 new CallbackAndContext(args->isolate(),
723 callback,
724 context.web_frame()->mainWorldScriptContext());
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));
734 return true;
737 bool GpuBenchmarking::Tap(gin::Arguments* args) {
738 GpuBenchmarkingContext context;
739 if (!context.Init(false))
740 return false;
742 float position_x;
743 float position_y;
744 v8::Handle<v8::Function> callback;
745 int duration_ms = 50;
746 int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
748 if (!GetArg(args, &position_x) ||
749 !GetArg(args, &position_y) ||
750 !GetOptionalArg(args, &callback) ||
751 !GetOptionalArg(args, &duration_ms) ||
752 !GetOptionalArg(args, &gesture_source_type)) {
753 return false;
756 scoped_ptr<SyntheticTapGestureParams> gesture_params(
757 new SyntheticTapGestureParams);
759 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
760 float page_scale_factor = context.web_view()->pageScaleFactor();
762 gesture_params->position.SetPoint(position_x * page_scale_factor,
763 position_y * page_scale_factor);
764 gesture_params->duration_ms = duration_ms;
766 if (gesture_source_type < 0 ||
767 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
768 return false;
770 gesture_params->gesture_source_type =
771 static_cast<SyntheticGestureParams::GestureSourceType>(
772 gesture_source_type);
774 scoped_refptr<CallbackAndContext> callback_and_context =
775 new CallbackAndContext(args->isolate(),
776 callback,
777 context.web_frame()->mainWorldScriptContext());
779 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
780 // progress, we will leak the callback and context. This needs to be fixed,
781 // somehow.
782 context.render_view_impl()->QueueSyntheticGesture(
783 gesture_params.Pass(),
784 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
786 return true;
789 void GpuBenchmarking::ClearImageCache() {
790 WebImageCache::clear();
793 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
794 GpuBenchmarkingContext context;
795 if (!context.Init(true))
796 return 0;
798 std::string name;
799 v8::Handle<v8::Function> callback;
800 v8::Handle<v8::Object> arguments;
802 if (!GetArg(args, &name) || !GetArg(args, &callback) ||
803 !GetOptionalArg(args, &arguments)) {
804 return 0;
807 scoped_refptr<CallbackAndContext> callback_and_context =
808 new CallbackAndContext(args->isolate(),
809 callback,
810 context.web_frame()->mainWorldScriptContext());
812 scoped_ptr<V8ValueConverter> converter =
813 make_scoped_ptr(V8ValueConverter::create());
814 v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
815 scoped_ptr<base::Value> value =
816 make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
818 return context.compositor()->ScheduleMicroBenchmark(
819 name,
820 value.Pass(),
821 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
824 bool GpuBenchmarking::SendMessageToMicroBenchmark(
825 int id,
826 v8::Handle<v8::Object> message) {
827 GpuBenchmarkingContext context;
828 if (!context.Init(true))
829 return false;
831 scoped_ptr<V8ValueConverter> converter =
832 make_scoped_ptr(V8ValueConverter::create());
833 v8::Handle<v8::Context> v8_context =
834 context.web_frame()->mainWorldScriptContext();
835 scoped_ptr<base::Value> value =
836 make_scoped_ptr(converter->FromV8Value(message, v8_context));
838 return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
841 bool GpuBenchmarking::HasGpuProcess() {
842 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
843 return !!gpu_channel;
846 } // namespace content