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"
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
;
54 class PNGSerializer
: public SkPixelSerializer
{
56 bool onUseEncodedData(const void* data
, size_t len
) override
{ return true; }
58 SkData
* onEncodePixels(const SkImageInfo
& info
,
60 size_t row_bytes
) override
{
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());
73 class SkPictureSerializer
{
75 explicit SkPictureSerializer(const base::FilePath
& dirpath
)
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();
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.
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
);
111 base::FilePath dirpath_
;
115 template <typename T
>
116 bool GetArg(gin::Arguments
* args
, T
* value
) {
117 if (!args
->GetNext(value
)) {
125 bool GetArg(gin::Arguments
* args
, int* value
) {
127 bool ret
= GetArg(args
, &number
);
132 template <typename T
>
133 bool GetOptionalArg(gin::Arguments
* args
, T
* value
) {
134 if (args
->PeekNext().IsEmpty())
136 if (args
->PeekNext()->IsUndefined()) {
140 return GetArg(args
, value
);
143 class CallbackAndContext
: public base::RefCounted
<CallbackAndContext
> {
145 CallbackAndContext(v8::Isolate
* isolate
,
146 v8::Local
<v8::Function
> callback
,
147 v8::Local
<v8::Context
> context
)
148 : isolate_(isolate
) {
149 callback_
.Reset(isolate_
, callback
);
150 context_
.Reset(isolate_
, context
);
153 v8::Isolate
* isolate() {
157 v8::Local
<v8::Function
> GetCallback() {
158 return v8::Local
<v8::Function
>::New(isolate_
, callback_
);
161 v8::Local
<v8::Context
> GetContext() {
162 return v8::Local
<v8::Context
>::New(isolate_
, context_
);
166 friend class base::RefCounted
<CallbackAndContext
>;
168 virtual ~CallbackAndContext() {
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
{
181 GpuBenchmarkingContext()
184 render_view_impl_(NULL
),
187 bool Init(bool init_compositor
) {
188 web_frame_
= WebLocalFrame::frameForCurrentContext();
192 web_view_
= web_frame_
->view();
198 render_view_impl_
= RenderViewImpl::FromWebView(web_view_
);
199 if (!render_view_impl_
) {
205 if (!init_compositor
)
208 compositor_
= render_view_impl_
->compositor();
212 render_view_impl_
= NULL
;
219 WebLocalFrame
* web_frame() const {
220 DCHECK(web_frame_
!= NULL
);
223 WebView
* web_view() const {
224 DCHECK(web_view_
!= NULL
);
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
);
237 WebLocalFrame
* web_frame_
;
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::Local
<v8::Context
> context
= callback_and_context
->GetContext();
251 v8::Context::Scope
context_scope(context
);
252 WebLocalFrame
* frame
= WebLocalFrame::frameForContext(context
);
254 scoped_ptr
<V8ValueConverter
> converter
=
255 make_scoped_ptr(V8ValueConverter::create());
256 v8::Local
<v8::Value
> value
= converter
->ToV8Value(result
.get(), context
);
257 v8::Local
<v8::Value
> argv
[] = { value
};
259 frame
->callFunctionEvenIfScriptDisabled(
260 callback_and_context
->GetCallback(),
261 v8::Object::New(isolate
),
267 void OnSyntheticGestureCompleted(CallbackAndContext
* callback_and_context
) {
268 v8::Isolate
* isolate
= callback_and_context
->isolate();
269 v8::HandleScope
scope(isolate
);
270 v8::Local
<v8::Context
> context
= callback_and_context
->GetContext();
271 v8::Context::Scope
context_scope(context
);
272 WebLocalFrame
* frame
= WebLocalFrame::frameForContext(context
);
274 frame
->callFunctionEvenIfScriptDisabled(
275 callback_and_context
->GetCallback(), v8::Object::New(isolate
), 0, NULL
);
279 bool BeginSmoothScroll(v8::Isolate
* isolate
,
280 float pixels_to_scroll
,
281 v8::Local
<v8::Function
> callback
,
282 int gesture_source_type
,
283 const std::string
& direction
,
284 float speed_in_pixels_s
,
288 GpuBenchmarkingContext context
;
289 if (!context
.Init(false))
292 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
293 float page_scale_factor
= context
.web_view()->pageScaleFactor();
295 if (gesture_source_type
== SyntheticGestureParams::MOUSE_INPUT
) {
296 // Ensure the mouse is centered and visible, in case it will
297 // trigger any hover or mousemove effects.
298 context
.web_view()->setIsActive(true);
299 blink::WebRect contentRect
=
300 context
.web_view()->mainFrame()->visibleContentRect();
301 blink::WebMouseEvent mouseMove
;
302 mouseMove
.type
= blink::WebInputEvent::MouseMove
;
303 mouseMove
.x
= (contentRect
.x
+ contentRect
.width
/ 2) * page_scale_factor
;
304 mouseMove
.y
= (contentRect
.y
+ contentRect
.height
/ 2) * page_scale_factor
;
305 context
.web_view()->handleInputEvent(mouseMove
);
306 context
.web_view()->setCursorVisibilityState(true);
309 scoped_refptr
<CallbackAndContext
> callback_and_context
=
310 new CallbackAndContext(
311 isolate
, callback
, context
.web_frame()->mainWorldScriptContext());
313 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
314 new SyntheticSmoothScrollGestureParams
);
316 if (gesture_source_type
< 0 ||
317 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
320 gesture_params
->gesture_source_type
=
321 static_cast<SyntheticGestureParams::GestureSourceType
>(
322 gesture_source_type
);
324 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
325 gesture_params
->prevent_fling
= prevent_fling
;
327 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
328 start_y
* page_scale_factor
);
330 float distance_length
= pixels_to_scroll
* page_scale_factor
;
331 gfx::Vector2dF distance
;
332 if (direction
== "down")
333 distance
.set_y(-distance_length
);
334 else if (direction
== "up")
335 distance
.set_y(distance_length
);
336 else if (direction
== "right")
337 distance
.set_x(-distance_length
);
338 else if (direction
== "left")
339 distance
.set_x(distance_length
);
340 else if (direction
== "upleft") {
341 distance
.set_y(distance_length
);
342 distance
.set_x(distance_length
);
343 } else if (direction
== "upright") {
344 distance
.set_y(distance_length
);
345 distance
.set_x(-distance_length
);
346 } else if (direction
== "downleft") {
347 distance
.set_y(-distance_length
);
348 distance
.set_x(distance_length
);
349 } else if (direction
== "downright") {
350 distance
.set_y(-distance_length
);
351 distance
.set_x(-distance_length
);
355 gesture_params
->distances
.push_back(distance
);
357 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
358 // progress, we will leak the callback and context. This needs to be fixed,
360 context
.render_view_impl()->QueueSyntheticGesture(
361 gesture_params
.Pass(),
362 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
367 bool BeginSmoothDrag(v8::Isolate
* isolate
,
372 v8::Local
<v8::Function
> callback
,
373 int gesture_source_type
,
374 float speed_in_pixels_s
) {
375 GpuBenchmarkingContext context
;
376 if (!context
.Init(false))
378 scoped_refptr
<CallbackAndContext
> callback_and_context
=
379 new CallbackAndContext(isolate
, callback
,
380 context
.web_frame()->mainWorldScriptContext());
382 scoped_ptr
<SyntheticSmoothDragGestureParams
> gesture_params(
383 new SyntheticSmoothDragGestureParams
);
385 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
386 float page_scale_factor
= context
.web_view()->pageScaleFactor();
388 gesture_params
->start_point
.SetPoint(start_x
* page_scale_factor
,
389 start_y
* page_scale_factor
);
390 gfx::PointF
end_point(end_x
* page_scale_factor
,
391 end_y
* page_scale_factor
);
392 gfx::Vector2dF distance
= end_point
- gesture_params
->start_point
;
393 gesture_params
->distances
.push_back(distance
);
394 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
* page_scale_factor
;
395 gesture_params
->gesture_source_type
=
396 static_cast<SyntheticGestureParams::GestureSourceType
>(
397 gesture_source_type
);
399 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
400 // progress, we will leak the callback and context. This needs to be fixed,
402 context
.render_view_impl()->QueueSyntheticGesture(
403 gesture_params
.Pass(),
404 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
411 gin::WrapperInfo
GpuBenchmarking::kWrapperInfo
= {gin::kEmbedderNativeGin
};
414 void GpuBenchmarking::Install(blink::WebFrame
* frame
) {
415 v8::Isolate
* isolate
= blink::mainThreadIsolate();
416 v8::HandleScope
handle_scope(isolate
);
417 v8::Local
<v8::Context
> context
= frame
->mainWorldScriptContext();
418 if (context
.IsEmpty())
421 v8::Context::Scope
context_scope(context
);
423 gin::Handle
<GpuBenchmarking
> controller
=
424 gin::CreateHandle(isolate
, new GpuBenchmarking());
425 if (controller
.IsEmpty())
428 v8::Local
<v8::Object
> chrome
= GetOrCreateChromeObject(isolate
,
430 chrome
->Set(gin::StringToV8(isolate
, "gpuBenchmarking"), controller
.ToV8());
433 GpuBenchmarking::GpuBenchmarking() {
436 GpuBenchmarking::~GpuBenchmarking() {
439 gin::ObjectTemplateBuilder
GpuBenchmarking::GetObjectTemplateBuilder(
440 v8::Isolate
* isolate
) {
441 return gin::Wrappable
<GpuBenchmarking
>::GetObjectTemplateBuilder(isolate
)
442 .SetMethod("setNeedsDisplayOnAllLayers",
443 &GpuBenchmarking::SetNeedsDisplayOnAllLayers
)
444 .SetMethod("setRasterizeOnlyVisibleContent",
445 &GpuBenchmarking::SetRasterizeOnlyVisibleContent
)
446 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture
)
447 .SetValue("DEFAULT_INPUT", 0)
448 .SetValue("TOUCH_INPUT", 1)
449 .SetValue("MOUSE_INPUT", 2)
450 .SetMethod("gestureSourceTypeSupported",
451 &GpuBenchmarking::GestureSourceTypeSupported
)
452 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy
)
453 .SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag
)
454 .SetMethod("swipe", &GpuBenchmarking::Swipe
)
455 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce
)
456 // TODO(dominikg): Remove once JS interface changes have rolled into
458 .SetValue("newPinchInterface", true)
459 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy
)
460 .SetMethod("tap", &GpuBenchmarking::Tap
)
461 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache
)
462 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark
)
463 .SetMethod("sendMessageToMicroBenchmark",
464 &GpuBenchmarking::SendMessageToMicroBenchmark
)
465 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess
);
468 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
469 GpuBenchmarkingContext context
;
470 if (!context
.Init(true))
473 context
.compositor()->SetNeedsDisplayOnAllLayers();
476 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
477 GpuBenchmarkingContext context
;
478 if (!context
.Init(true))
481 context
.compositor()->SetRasterizeOnlyVisibleContent();
484 void GpuBenchmarking::PrintToSkPicture(v8::Isolate
* isolate
,
485 const std::string
& dirname
) {
486 GpuBenchmarkingContext context
;
487 if (!context
.Init(true))
490 const cc::Layer
* root_layer
= context
.compositor()->GetRootLayer();
494 base::FilePath dirpath
= base::FilePath::FromUTF8Unsafe(dirname
);
495 if (!base::CreateDirectory(dirpath
) ||
496 !base::PathIsWritable(dirpath
)) {
497 std::string
msg("Path is not writable: ");
498 msg
.append(dirpath
.MaybeAsASCII());
499 isolate
->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
500 isolate
, msg
.c_str(), v8::String::kNormalString
, msg
.length())));
504 SkPictureSerializer
serializer(dirpath
);
505 serializer
.Serialize(root_layer
);
508 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type
) {
509 if (gesture_source_type
< 0 ||
510 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
514 return SyntheticGestureParams::IsGestureSourceTypeSupported(
515 static_cast<SyntheticGestureParams::GestureSourceType
>(
516 gesture_source_type
));
519 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments
* args
) {
520 GpuBenchmarkingContext context
;
521 if (!context
.Init(true))
524 float page_scale_factor
= context
.web_view()->pageScaleFactor();
525 blink::WebRect rect
= context
.render_view_impl()->windowRect();
527 float pixels_to_scroll
= 0;
528 v8::Local
<v8::Function
> callback
;
529 float start_x
= rect
.width
/ (page_scale_factor
* 2);
530 float start_y
= rect
.height
/ (page_scale_factor
* 2);
531 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
532 std::string direction
= "down";
533 float speed_in_pixels_s
= 800;
535 if (!GetOptionalArg(args
, &pixels_to_scroll
) ||
536 !GetOptionalArg(args
, &callback
) ||
537 !GetOptionalArg(args
, &start_x
) ||
538 !GetOptionalArg(args
, &start_y
) ||
539 !GetOptionalArg(args
, &gesture_source_type
) ||
540 !GetOptionalArg(args
, &direction
) ||
541 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
545 return BeginSmoothScroll(args
->isolate(),
556 bool GpuBenchmarking::SmoothDrag(gin::Arguments
* args
) {
557 GpuBenchmarkingContext context
;
558 if (!context
.Init(true))
565 v8::Local
<v8::Function
> callback
;
566 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
567 float speed_in_pixels_s
= 800;
569 if (!GetArg(args
, &start_x
) ||
570 !GetArg(args
, &start_y
) ||
571 !GetArg(args
, &end_x
) ||
572 !GetArg(args
, &end_y
) ||
573 !GetOptionalArg(args
, &callback
) ||
574 !GetOptionalArg(args
, &gesture_source_type
) ||
575 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
579 return BeginSmoothDrag(args
->isolate(),
589 bool GpuBenchmarking::Swipe(gin::Arguments
* args
) {
590 GpuBenchmarkingContext context
;
591 if (!context
.Init(true))
594 float page_scale_factor
= context
.web_view()->pageScaleFactor();
595 blink::WebRect rect
= context
.render_view_impl()->windowRect();
597 std::string direction
= "up";
598 float pixels_to_scroll
= 0;
599 v8::Local
<v8::Function
> callback
;
600 float start_x
= rect
.width
/ (page_scale_factor
* 2);
601 float start_y
= rect
.height
/ (page_scale_factor
* 2);
602 float speed_in_pixels_s
= 800;
604 if (!GetOptionalArg(args
, &direction
) ||
605 !GetOptionalArg(args
, &pixels_to_scroll
) ||
606 !GetOptionalArg(args
, &callback
) ||
607 !GetOptionalArg(args
, &start_x
) ||
608 !GetOptionalArg(args
, &start_y
) ||
609 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
613 return BeginSmoothScroll(args
->isolate(),
624 bool GpuBenchmarking::ScrollBounce(gin::Arguments
* args
) {
625 GpuBenchmarkingContext context
;
626 if (!context
.Init(false))
629 float page_scale_factor
= context
.web_view()->pageScaleFactor();
630 blink::WebRect rect
= context
.render_view_impl()->windowRect();
632 std::string direction
= "down";
633 float distance_length
= 0;
634 float overscroll_length
= 0;
635 int repeat_count
= 1;
636 v8::Local
<v8::Function
> callback
;
637 float start_x
= rect
.width
/ (page_scale_factor
* 2);
638 float start_y
= rect
.height
/ (page_scale_factor
* 2);
639 float speed_in_pixels_s
= 800;
641 if (!GetOptionalArg(args
, &direction
) ||
642 !GetOptionalArg(args
, &distance_length
) ||
643 !GetOptionalArg(args
, &overscroll_length
) ||
644 !GetOptionalArg(args
, &repeat_count
) ||
645 !GetOptionalArg(args
, &callback
) ||
646 !GetOptionalArg(args
, &start_x
) ||
647 !GetOptionalArg(args
, &start_y
) ||
648 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
652 scoped_refptr
<CallbackAndContext
> callback_and_context
=
653 new CallbackAndContext(args
->isolate(),
655 context
.web_frame()->mainWorldScriptContext());
657 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
658 new SyntheticSmoothScrollGestureParams
);
660 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
662 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
663 start_y
* page_scale_factor
);
665 distance_length
*= page_scale_factor
;
666 overscroll_length
*= page_scale_factor
;
667 gfx::Vector2dF distance
;
668 gfx::Vector2dF overscroll
;
669 if (direction
== "down") {
670 distance
.set_y(-distance_length
);
671 overscroll
.set_y(overscroll_length
);
672 } else if (direction
== "up") {
673 distance
.set_y(distance_length
);
674 overscroll
.set_y(-overscroll_length
);
675 } else if (direction
== "right") {
676 distance
.set_x(-distance_length
);
677 overscroll
.set_x(overscroll_length
);
678 } else if (direction
== "left") {
679 distance
.set_x(distance_length
);
680 overscroll
.set_x(-overscroll_length
);
685 for (int i
= 0; i
< repeat_count
; i
++) {
686 gesture_params
->distances
.push_back(distance
);
687 gesture_params
->distances
.push_back(-distance
+ overscroll
);
690 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
691 // progress, we will leak the callback and context. This needs to be fixed,
693 context
.render_view_impl()->QueueSyntheticGesture(
694 gesture_params
.Pass(),
695 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
700 bool GpuBenchmarking::PinchBy(gin::Arguments
* args
) {
701 GpuBenchmarkingContext context
;
702 if (!context
.Init(false))
708 v8::Local
<v8::Function
> callback
;
709 float relative_pointer_speed_in_pixels_s
= 800;
712 if (!GetArg(args
, &scale_factor
) ||
713 !GetArg(args
, &anchor_x
) ||
714 !GetArg(args
, &anchor_y
) ||
715 !GetOptionalArg(args
, &callback
) ||
716 !GetOptionalArg(args
, &relative_pointer_speed_in_pixels_s
)) {
720 scoped_ptr
<SyntheticPinchGestureParams
> gesture_params(
721 new SyntheticPinchGestureParams
);
723 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
724 float page_scale_factor
= context
.web_view()->pageScaleFactor();
726 gesture_params
->scale_factor
= scale_factor
;
727 gesture_params
->anchor
.SetPoint(anchor_x
* page_scale_factor
,
728 anchor_y
* page_scale_factor
);
729 gesture_params
->relative_pointer_speed_in_pixels_s
=
730 relative_pointer_speed_in_pixels_s
;
732 scoped_refptr
<CallbackAndContext
> callback_and_context
=
733 new CallbackAndContext(args
->isolate(),
735 context
.web_frame()->mainWorldScriptContext());
738 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
739 // progress, we will leak the callback and context. This needs to be fixed,
741 context
.render_view_impl()->QueueSyntheticGesture(
742 gesture_params
.Pass(),
743 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
748 bool GpuBenchmarking::Tap(gin::Arguments
* args
) {
749 GpuBenchmarkingContext context
;
750 if (!context
.Init(false))
755 v8::Local
<v8::Function
> callback
;
756 int duration_ms
= 50;
757 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
759 if (!GetArg(args
, &position_x
) ||
760 !GetArg(args
, &position_y
) ||
761 !GetOptionalArg(args
, &callback
) ||
762 !GetOptionalArg(args
, &duration_ms
) ||
763 !GetOptionalArg(args
, &gesture_source_type
)) {
767 scoped_ptr
<SyntheticTapGestureParams
> gesture_params(
768 new SyntheticTapGestureParams
);
770 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
771 float page_scale_factor
= context
.web_view()->pageScaleFactor();
773 gesture_params
->position
.SetPoint(position_x
* page_scale_factor
,
774 position_y
* page_scale_factor
);
775 gesture_params
->duration_ms
= duration_ms
;
777 if (gesture_source_type
< 0 ||
778 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
781 gesture_params
->gesture_source_type
=
782 static_cast<SyntheticGestureParams::GestureSourceType
>(
783 gesture_source_type
);
785 scoped_refptr
<CallbackAndContext
> callback_and_context
=
786 new CallbackAndContext(args
->isolate(),
788 context
.web_frame()->mainWorldScriptContext());
790 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
791 // progress, we will leak the callback and context. This needs to be fixed,
793 context
.render_view_impl()->QueueSyntheticGesture(
794 gesture_params
.Pass(),
795 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
800 void GpuBenchmarking::ClearImageCache() {
801 WebImageCache::clear();
804 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments
* args
) {
805 GpuBenchmarkingContext context
;
806 if (!context
.Init(true))
810 v8::Local
<v8::Function
> callback
;
811 v8::Local
<v8::Object
> arguments
;
813 if (!GetArg(args
, &name
) || !GetArg(args
, &callback
) ||
814 !GetOptionalArg(args
, &arguments
)) {
818 scoped_refptr
<CallbackAndContext
> callback_and_context
=
819 new CallbackAndContext(args
->isolate(),
821 context
.web_frame()->mainWorldScriptContext());
823 scoped_ptr
<V8ValueConverter
> converter
=
824 make_scoped_ptr(V8ValueConverter::create());
825 v8::Local
<v8::Context
> v8_context
= callback_and_context
->GetContext();
826 scoped_ptr
<base::Value
> value
=
827 make_scoped_ptr(converter
->FromV8Value(arguments
, v8_context
));
829 return context
.compositor()->ScheduleMicroBenchmark(
832 base::Bind(&OnMicroBenchmarkCompleted
, callback_and_context
));
835 bool GpuBenchmarking::SendMessageToMicroBenchmark(
837 v8::Local
<v8::Object
> message
) {
838 GpuBenchmarkingContext context
;
839 if (!context
.Init(true))
842 scoped_ptr
<V8ValueConverter
> converter
=
843 make_scoped_ptr(V8ValueConverter::create());
844 v8::Local
<v8::Context
> v8_context
=
845 context
.web_frame()->mainWorldScriptContext();
846 scoped_ptr
<base::Value
> value
=
847 make_scoped_ptr(converter
->FromV8Value(message
, v8_context
));
849 return context
.compositor()->SendMessageToMicroBenchmark(id
, value
.Pass());
852 bool GpuBenchmarking::HasGpuProcess() {
853 GpuChannelHost
* gpu_channel
= RenderThreadImpl::current()->GetGpuChannel();
854 return !!gpu_channel
;
857 } // namespace content