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/strings/string_number_conversions.h"
13 #include "cc/layers/layer.h"
14 #include "content/common/input/synthetic_gesture_params.h"
15 #include "content/common/input/synthetic_pinch_gesture_params.h"
16 #include "content/common/input/synthetic_smooth_drag_gesture_params.h"
17 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
18 #include "content/common/input/synthetic_tap_gesture_params.h"
19 #include "content/public/child/v8_value_converter.h"
20 #include "content/public/renderer/render_thread.h"
21 #include "content/renderer/chrome_object_extensions_utils.h"
22 #include "content/renderer/gpu/render_widget_compositor.h"
23 #include "content/renderer/render_thread_impl.h"
24 #include "content/renderer/render_view_impl.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"
29 #include "third_party/WebKit/public/web/WebImageCache.h"
30 #include "third_party/WebKit/public/web/WebKit.h"
31 #include "third_party/WebKit/public/web/WebLocalFrame.h"
32 #include "third_party/WebKit/public/web/WebView.h"
33 #include "third_party/skia/include/core/SkData.h"
34 #include "third_party/skia/include/core/SkGraphics.h"
35 #include "third_party/skia/include/core/SkPicture.h"
36 #include "third_party/skia/include/core/SkPixelRef.h"
37 #include "third_party/skia/include/core/SkPixelSerializer.h"
38 #include "third_party/skia/include/core/SkStream.h"
39 #include "ui/gfx/codec/png_codec.h"
40 #include "v8/include/v8.h"
42 using blink::WebCanvas
;
43 using blink::WebLocalFrame
;
44 using blink::WebImageCache
;
45 using blink::WebPrivatePtr
;
53 class PNGSerializer
: public SkPixelSerializer
{
55 bool onUseEncodedData(const void* data
, size_t len
) override
{ return true; }
57 SkData
* onEncodePixels(const SkImageInfo
& info
,
59 size_t row_bytes
) override
{
61 // The const_cast is fine, since we only read from the bitmap.
62 if (bm
.installPixels(info
, const_cast<void*>(pixels
), row_bytes
)) {
63 std::vector
<unsigned char> vector
;
64 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm
, false, &vector
)) {
65 return SkData::NewWithCopy(&vector
.front(), vector
.size());
72 class SkPictureSerializer
{
74 explicit SkPictureSerializer(const base::FilePath
& dirpath
)
77 // Let skia register known effect subclasses. This basically enables
78 // reflection on those subclasses required for picture serialization.
79 SkiaBenchmarking::Initialize();
82 // Recursively serializes the layer tree.
83 // Each layer in the tree is serialized into a separate skp file
84 // in the given directory.
85 void Serialize(const cc::Layer
* layer
) {
86 const cc::LayerList
& children
= layer
->children();
87 for (size_t i
= 0; i
< children
.size(); ++i
) {
88 Serialize(children
[i
].get());
91 skia::RefPtr
<SkPicture
> picture
= layer
->GetPicture();
95 // Serialize picture to file.
96 // TODO(alokp): Note that for this to work Chrome needs to be launched with
97 // --no-sandbox command-line flag. Get rid of this limitation.
99 std::string filename
= "layer_" + base::IntToString(layer_id_
++) + ".skp";
100 std::string filepath
= dirpath_
.AppendASCII(filename
).MaybeAsASCII();
101 DCHECK(!filepath
.empty());
102 SkFILEWStream
file(filepath
.c_str());
103 DCHECK(file
.isValid());
105 PNGSerializer serializer
;
106 picture
->serialize(&file
, &serializer
);
110 base::FilePath dirpath_
;
114 template <typename T
>
115 bool GetArg(gin::Arguments
* args
, T
* value
) {
116 if (!args
->GetNext(value
)) {
124 bool GetArg(gin::Arguments
* args
, int* value
) {
126 bool ret
= GetArg(args
, &number
);
131 template <typename T
>
132 bool GetOptionalArg(gin::Arguments
* args
, T
* value
) {
133 if (args
->PeekNext().IsEmpty())
135 if (args
->PeekNext()->IsUndefined()) {
139 return GetArg(args
, value
);
142 class CallbackAndContext
: public base::RefCounted
<CallbackAndContext
> {
144 CallbackAndContext(v8::Isolate
* isolate
,
145 v8::Local
<v8::Function
> callback
,
146 v8::Local
<v8::Context
> context
)
147 : isolate_(isolate
) {
148 callback_
.Reset(isolate_
, callback
);
149 context_
.Reset(isolate_
, context
);
152 v8::Isolate
* isolate() {
156 v8::Local
<v8::Function
> GetCallback() {
157 return v8::Local
<v8::Function
>::New(isolate_
, callback_
);
160 v8::Local
<v8::Context
> GetContext() {
161 return v8::Local
<v8::Context
>::New(isolate_
, context_
);
165 friend class base::RefCounted
<CallbackAndContext
>;
167 virtual ~CallbackAndContext() {
172 v8::Isolate
* isolate_
;
173 v8::Persistent
<v8::Function
> callback_
;
174 v8::Persistent
<v8::Context
> context_
;
175 DISALLOW_COPY_AND_ASSIGN(CallbackAndContext
);
178 class GpuBenchmarkingContext
{
180 GpuBenchmarkingContext()
183 render_view_impl_(NULL
),
186 bool Init(bool init_compositor
) {
187 web_frame_
= WebLocalFrame::frameForCurrentContext();
191 web_view_
= web_frame_
->view();
197 render_view_impl_
= RenderViewImpl::FromWebView(web_view_
);
198 if (!render_view_impl_
) {
204 if (!init_compositor
)
207 compositor_
= render_view_impl_
->compositor();
211 render_view_impl_
= NULL
;
218 WebLocalFrame
* web_frame() const {
219 DCHECK(web_frame_
!= NULL
);
222 WebView
* web_view() const {
223 DCHECK(web_view_
!= NULL
);
226 RenderViewImpl
* render_view_impl() const {
227 DCHECK(render_view_impl_
!= NULL
);
228 return render_view_impl_
;
230 RenderWidgetCompositor
* compositor() const {
231 DCHECK(compositor_
!= NULL
);
236 WebLocalFrame
* web_frame_
;
238 RenderViewImpl
* render_view_impl_
;
239 RenderWidgetCompositor
* compositor_
;
241 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext
);
244 void OnMicroBenchmarkCompleted(
245 CallbackAndContext
* callback_and_context
,
246 scoped_ptr
<base::Value
> result
) {
247 v8::Isolate
* isolate
= callback_and_context
->isolate();
248 v8::HandleScope
scope(isolate
);
249 v8::Local
<v8::Context
> context
= callback_and_context
->GetContext();
250 v8::Context::Scope
context_scope(context
);
251 WebLocalFrame
* frame
= WebLocalFrame::frameForContext(context
);
253 scoped_ptr
<V8ValueConverter
> converter
=
254 make_scoped_ptr(V8ValueConverter::create());
255 v8::Local
<v8::Value
> value
= converter
->ToV8Value(result
.get(), context
);
256 v8::Local
<v8::Value
> argv
[] = { value
};
258 frame
->callFunctionEvenIfScriptDisabled(
259 callback_and_context
->GetCallback(),
260 v8::Object::New(isolate
),
266 void OnSyntheticGestureCompleted(CallbackAndContext
* callback_and_context
) {
267 v8::Isolate
* isolate
= callback_and_context
->isolate();
268 v8::HandleScope
scope(isolate
);
269 v8::Local
<v8::Context
> context
= callback_and_context
->GetContext();
270 v8::Context::Scope
context_scope(context
);
271 WebLocalFrame
* frame
= WebLocalFrame::frameForContext(context
);
273 frame
->callFunctionEvenIfScriptDisabled(
274 callback_and_context
->GetCallback(), v8::Object::New(isolate
), 0, NULL
);
278 bool BeginSmoothScroll(v8::Isolate
* isolate
,
279 float pixels_to_scroll
,
280 v8::Local
<v8::Function
> callback
,
281 int gesture_source_type
,
282 const std::string
& direction
,
283 float speed_in_pixels_s
,
287 GpuBenchmarkingContext context
;
288 if (!context
.Init(false))
291 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
292 float page_scale_factor
= context
.web_view()->pageScaleFactor();
294 if (gesture_source_type
== SyntheticGestureParams::MOUSE_INPUT
) {
295 // Ensure the mouse is centered and visible, in case it will
296 // trigger any hover or mousemove effects.
297 context
.web_view()->setIsActive(true);
298 blink::WebRect contentRect
=
299 context
.web_view()->mainFrame()->visibleContentRect();
300 blink::WebMouseEvent mouseMove
;
301 mouseMove
.type
= blink::WebInputEvent::MouseMove
;
302 mouseMove
.x
= (contentRect
.x
+ contentRect
.width
/ 2) * page_scale_factor
;
303 mouseMove
.y
= (contentRect
.y
+ contentRect
.height
/ 2) * page_scale_factor
;
304 context
.web_view()->handleInputEvent(mouseMove
);
305 context
.web_view()->setCursorVisibilityState(true);
308 scoped_refptr
<CallbackAndContext
> callback_and_context
=
309 new CallbackAndContext(
310 isolate
, callback
, context
.web_frame()->mainWorldScriptContext());
312 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
313 new SyntheticSmoothScrollGestureParams
);
315 if (gesture_source_type
< 0 ||
316 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
319 gesture_params
->gesture_source_type
=
320 static_cast<SyntheticGestureParams::GestureSourceType
>(
321 gesture_source_type
);
323 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
324 gesture_params
->prevent_fling
= prevent_fling
;
326 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
327 start_y
* page_scale_factor
);
329 float distance_length
= pixels_to_scroll
* page_scale_factor
;
330 gfx::Vector2dF distance
;
331 if (direction
== "down")
332 distance
.set_y(-distance_length
);
333 else if (direction
== "up")
334 distance
.set_y(distance_length
);
335 else if (direction
== "right")
336 distance
.set_x(-distance_length
);
337 else if (direction
== "left")
338 distance
.set_x(distance_length
);
339 else if (direction
== "upleft") {
340 distance
.set_y(distance_length
);
341 distance
.set_x(distance_length
);
342 } else if (direction
== "upright") {
343 distance
.set_y(distance_length
);
344 distance
.set_x(-distance_length
);
345 } else if (direction
== "downleft") {
346 distance
.set_y(-distance_length
);
347 distance
.set_x(distance_length
);
348 } else if (direction
== "downright") {
349 distance
.set_y(-distance_length
);
350 distance
.set_x(-distance_length
);
354 gesture_params
->distances
.push_back(distance
);
356 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
357 // progress, we will leak the callback and context. This needs to be fixed,
359 context
.render_view_impl()->QueueSyntheticGesture(
360 gesture_params
.Pass(),
361 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
366 bool BeginSmoothDrag(v8::Isolate
* isolate
,
371 v8::Local
<v8::Function
> callback
,
372 int gesture_source_type
,
373 float speed_in_pixels_s
) {
374 GpuBenchmarkingContext context
;
375 if (!context
.Init(false))
377 scoped_refptr
<CallbackAndContext
> callback_and_context
=
378 new CallbackAndContext(isolate
, callback
,
379 context
.web_frame()->mainWorldScriptContext());
381 scoped_ptr
<SyntheticSmoothDragGestureParams
> gesture_params(
382 new SyntheticSmoothDragGestureParams
);
384 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
385 float page_scale_factor
= context
.web_view()->pageScaleFactor();
387 gesture_params
->start_point
.SetPoint(start_x
* page_scale_factor
,
388 start_y
* page_scale_factor
);
389 gfx::PointF
end_point(end_x
* page_scale_factor
,
390 end_y
* page_scale_factor
);
391 gfx::Vector2dF distance
= end_point
- gesture_params
->start_point
;
392 gesture_params
->distances
.push_back(distance
);
393 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
* page_scale_factor
;
394 gesture_params
->gesture_source_type
=
395 static_cast<SyntheticGestureParams::GestureSourceType
>(
396 gesture_source_type
);
398 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
399 // progress, we will leak the callback and context. This needs to be fixed,
401 context
.render_view_impl()->QueueSyntheticGesture(
402 gesture_params
.Pass(),
403 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
410 gin::WrapperInfo
GpuBenchmarking::kWrapperInfo
= {gin::kEmbedderNativeGin
};
413 void GpuBenchmarking::Install(blink::WebFrame
* frame
) {
414 v8::Isolate
* isolate
= blink::mainThreadIsolate();
415 v8::HandleScope
handle_scope(isolate
);
416 v8::Local
<v8::Context
> context
= frame
->mainWorldScriptContext();
417 if (context
.IsEmpty())
420 v8::Context::Scope
context_scope(context
);
422 gin::Handle
<GpuBenchmarking
> controller
=
423 gin::CreateHandle(isolate
, new GpuBenchmarking());
424 if (controller
.IsEmpty())
427 v8::Local
<v8::Object
> chrome
= GetOrCreateChromeObject(isolate
,
429 chrome
->Set(gin::StringToV8(isolate
, "gpuBenchmarking"), controller
.ToV8());
432 GpuBenchmarking::GpuBenchmarking() {
435 GpuBenchmarking::~GpuBenchmarking() {
438 gin::ObjectTemplateBuilder
GpuBenchmarking::GetObjectTemplateBuilder(
439 v8::Isolate
* isolate
) {
440 return gin::Wrappable
<GpuBenchmarking
>::GetObjectTemplateBuilder(isolate
)
441 .SetMethod("setNeedsDisplayOnAllLayers",
442 &GpuBenchmarking::SetNeedsDisplayOnAllLayers
)
443 .SetMethod("setRasterizeOnlyVisibleContent",
444 &GpuBenchmarking::SetRasterizeOnlyVisibleContent
)
445 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture
)
446 .SetValue("DEFAULT_INPUT", 0)
447 .SetValue("TOUCH_INPUT", 1)
448 .SetValue("MOUSE_INPUT", 2)
449 .SetMethod("gestureSourceTypeSupported",
450 &GpuBenchmarking::GestureSourceTypeSupported
)
451 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy
)
452 .SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag
)
453 .SetMethod("swipe", &GpuBenchmarking::Swipe
)
454 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce
)
455 // TODO(dominikg): Remove once JS interface changes have rolled into
457 .SetValue("newPinchInterface", true)
458 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy
)
459 .SetMethod("tap", &GpuBenchmarking::Tap
)
460 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache
)
461 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark
)
462 .SetMethod("sendMessageToMicroBenchmark",
463 &GpuBenchmarking::SendMessageToMicroBenchmark
)
464 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess
);
467 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
468 GpuBenchmarkingContext context
;
469 if (!context
.Init(true))
472 context
.compositor()->SetNeedsDisplayOnAllLayers();
475 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
476 GpuBenchmarkingContext context
;
477 if (!context
.Init(true))
480 context
.compositor()->SetRasterizeOnlyVisibleContent();
483 void GpuBenchmarking::PrintToSkPicture(v8::Isolate
* isolate
,
484 const std::string
& dirname
) {
485 GpuBenchmarkingContext context
;
486 if (!context
.Init(true))
489 const cc::Layer
* root_layer
= context
.compositor()->GetRootLayer();
493 base::FilePath dirpath
= base::FilePath::FromUTF8Unsafe(dirname
);
494 if (!base::CreateDirectory(dirpath
) ||
495 !base::PathIsWritable(dirpath
)) {
496 std::string
msg("Path is not writable: ");
497 msg
.append(dirpath
.MaybeAsASCII());
498 isolate
->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
499 isolate
, msg
.c_str(), v8::String::kNormalString
, msg
.length())));
503 SkPictureSerializer
serializer(dirpath
);
504 serializer
.Serialize(root_layer
);
507 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type
) {
508 if (gesture_source_type
< 0 ||
509 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
513 return SyntheticGestureParams::IsGestureSourceTypeSupported(
514 static_cast<SyntheticGestureParams::GestureSourceType
>(
515 gesture_source_type
));
518 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments
* args
) {
519 GpuBenchmarkingContext context
;
520 if (!context
.Init(true))
523 float page_scale_factor
= context
.web_view()->pageScaleFactor();
524 blink::WebRect rect
= context
.render_view_impl()->windowRect();
526 float pixels_to_scroll
= 0;
527 v8::Local
<v8::Function
> callback
;
528 float start_x
= rect
.width
/ (page_scale_factor
* 2);
529 float start_y
= rect
.height
/ (page_scale_factor
* 2);
530 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
531 std::string direction
= "down";
532 float speed_in_pixels_s
= 800;
534 if (!GetOptionalArg(args
, &pixels_to_scroll
) ||
535 !GetOptionalArg(args
, &callback
) ||
536 !GetOptionalArg(args
, &start_x
) ||
537 !GetOptionalArg(args
, &start_y
) ||
538 !GetOptionalArg(args
, &gesture_source_type
) ||
539 !GetOptionalArg(args
, &direction
) ||
540 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
544 return BeginSmoothScroll(args
->isolate(),
555 bool GpuBenchmarking::SmoothDrag(gin::Arguments
* args
) {
556 GpuBenchmarkingContext context
;
557 if (!context
.Init(true))
564 v8::Local
<v8::Function
> callback
;
565 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
566 float speed_in_pixels_s
= 800;
568 if (!GetArg(args
, &start_x
) ||
569 !GetArg(args
, &start_y
) ||
570 !GetArg(args
, &end_x
) ||
571 !GetArg(args
, &end_y
) ||
572 !GetOptionalArg(args
, &callback
) ||
573 !GetOptionalArg(args
, &gesture_source_type
) ||
574 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
578 return BeginSmoothDrag(args
->isolate(),
588 bool GpuBenchmarking::Swipe(gin::Arguments
* args
) {
589 GpuBenchmarkingContext context
;
590 if (!context
.Init(true))
593 float page_scale_factor
= context
.web_view()->pageScaleFactor();
594 blink::WebRect rect
= context
.render_view_impl()->windowRect();
596 std::string direction
= "up";
597 float pixels_to_scroll
= 0;
598 v8::Local
<v8::Function
> callback
;
599 float start_x
= rect
.width
/ (page_scale_factor
* 2);
600 float start_y
= rect
.height
/ (page_scale_factor
* 2);
601 float speed_in_pixels_s
= 800;
603 if (!GetOptionalArg(args
, &direction
) ||
604 !GetOptionalArg(args
, &pixels_to_scroll
) ||
605 !GetOptionalArg(args
, &callback
) ||
606 !GetOptionalArg(args
, &start_x
) ||
607 !GetOptionalArg(args
, &start_y
) ||
608 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
612 return BeginSmoothScroll(args
->isolate(),
623 bool GpuBenchmarking::ScrollBounce(gin::Arguments
* args
) {
624 GpuBenchmarkingContext context
;
625 if (!context
.Init(false))
628 float page_scale_factor
= context
.web_view()->pageScaleFactor();
629 blink::WebRect rect
= context
.render_view_impl()->windowRect();
631 std::string direction
= "down";
632 float distance_length
= 0;
633 float overscroll_length
= 0;
634 int repeat_count
= 1;
635 v8::Local
<v8::Function
> callback
;
636 float start_x
= rect
.width
/ (page_scale_factor
* 2);
637 float start_y
= rect
.height
/ (page_scale_factor
* 2);
638 float speed_in_pixels_s
= 800;
640 if (!GetOptionalArg(args
, &direction
) ||
641 !GetOptionalArg(args
, &distance_length
) ||
642 !GetOptionalArg(args
, &overscroll_length
) ||
643 !GetOptionalArg(args
, &repeat_count
) ||
644 !GetOptionalArg(args
, &callback
) ||
645 !GetOptionalArg(args
, &start_x
) ||
646 !GetOptionalArg(args
, &start_y
) ||
647 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
651 scoped_refptr
<CallbackAndContext
> callback_and_context
=
652 new CallbackAndContext(args
->isolate(),
654 context
.web_frame()->mainWorldScriptContext());
656 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
657 new SyntheticSmoothScrollGestureParams
);
659 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
661 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
662 start_y
* page_scale_factor
);
664 distance_length
*= page_scale_factor
;
665 overscroll_length
*= page_scale_factor
;
666 gfx::Vector2dF distance
;
667 gfx::Vector2dF overscroll
;
668 if (direction
== "down") {
669 distance
.set_y(-distance_length
);
670 overscroll
.set_y(overscroll_length
);
671 } else if (direction
== "up") {
672 distance
.set_y(distance_length
);
673 overscroll
.set_y(-overscroll_length
);
674 } else if (direction
== "right") {
675 distance
.set_x(-distance_length
);
676 overscroll
.set_x(overscroll_length
);
677 } else if (direction
== "left") {
678 distance
.set_x(distance_length
);
679 overscroll
.set_x(-overscroll_length
);
684 for (int i
= 0; i
< repeat_count
; i
++) {
685 gesture_params
->distances
.push_back(distance
);
686 gesture_params
->distances
.push_back(-distance
+ overscroll
);
689 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
690 // progress, we will leak the callback and context. This needs to be fixed,
692 context
.render_view_impl()->QueueSyntheticGesture(
693 gesture_params
.Pass(),
694 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
699 bool GpuBenchmarking::PinchBy(gin::Arguments
* args
) {
700 GpuBenchmarkingContext context
;
701 if (!context
.Init(false))
707 v8::Local
<v8::Function
> callback
;
708 float relative_pointer_speed_in_pixels_s
= 800;
711 if (!GetArg(args
, &scale_factor
) ||
712 !GetArg(args
, &anchor_x
) ||
713 !GetArg(args
, &anchor_y
) ||
714 !GetOptionalArg(args
, &callback
) ||
715 !GetOptionalArg(args
, &relative_pointer_speed_in_pixels_s
)) {
719 scoped_ptr
<SyntheticPinchGestureParams
> gesture_params(
720 new SyntheticPinchGestureParams
);
722 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
723 float page_scale_factor
= context
.web_view()->pageScaleFactor();
725 gesture_params
->scale_factor
= scale_factor
;
726 gesture_params
->anchor
.SetPoint(anchor_x
* page_scale_factor
,
727 anchor_y
* page_scale_factor
);
728 gesture_params
->relative_pointer_speed_in_pixels_s
=
729 relative_pointer_speed_in_pixels_s
;
731 scoped_refptr
<CallbackAndContext
> callback_and_context
=
732 new CallbackAndContext(args
->isolate(),
734 context
.web_frame()->mainWorldScriptContext());
737 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
738 // progress, we will leak the callback and context. This needs to be fixed,
740 context
.render_view_impl()->QueueSyntheticGesture(
741 gesture_params
.Pass(),
742 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
747 bool GpuBenchmarking::Tap(gin::Arguments
* args
) {
748 GpuBenchmarkingContext context
;
749 if (!context
.Init(false))
754 v8::Local
<v8::Function
> callback
;
755 int duration_ms
= 50;
756 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
758 if (!GetArg(args
, &position_x
) ||
759 !GetArg(args
, &position_y
) ||
760 !GetOptionalArg(args
, &callback
) ||
761 !GetOptionalArg(args
, &duration_ms
) ||
762 !GetOptionalArg(args
, &gesture_source_type
)) {
766 scoped_ptr
<SyntheticTapGestureParams
> gesture_params(
767 new SyntheticTapGestureParams
);
769 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
770 float page_scale_factor
= context
.web_view()->pageScaleFactor();
772 gesture_params
->position
.SetPoint(position_x
* page_scale_factor
,
773 position_y
* page_scale_factor
);
774 gesture_params
->duration_ms
= duration_ms
;
776 if (gesture_source_type
< 0 ||
777 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
780 gesture_params
->gesture_source_type
=
781 static_cast<SyntheticGestureParams::GestureSourceType
>(
782 gesture_source_type
);
784 scoped_refptr
<CallbackAndContext
> callback_and_context
=
785 new CallbackAndContext(args
->isolate(),
787 context
.web_frame()->mainWorldScriptContext());
789 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
790 // progress, we will leak the callback and context. This needs to be fixed,
792 context
.render_view_impl()->QueueSyntheticGesture(
793 gesture_params
.Pass(),
794 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
799 void GpuBenchmarking::ClearImageCache() {
800 WebImageCache::clear();
803 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments
* args
) {
804 GpuBenchmarkingContext context
;
805 if (!context
.Init(true))
809 v8::Local
<v8::Function
> callback
;
810 v8::Local
<v8::Object
> arguments
;
812 if (!GetArg(args
, &name
) || !GetArg(args
, &callback
) ||
813 !GetOptionalArg(args
, &arguments
)) {
817 scoped_refptr
<CallbackAndContext
> callback_and_context
=
818 new CallbackAndContext(args
->isolate(),
820 context
.web_frame()->mainWorldScriptContext());
822 scoped_ptr
<V8ValueConverter
> converter
=
823 make_scoped_ptr(V8ValueConverter::create());
824 v8::Local
<v8::Context
> v8_context
= callback_and_context
->GetContext();
825 scoped_ptr
<base::Value
> value
=
826 make_scoped_ptr(converter
->FromV8Value(arguments
, v8_context
));
828 return context
.compositor()->ScheduleMicroBenchmark(
831 base::Bind(&OnMicroBenchmarkCompleted
, callback_and_context
));
834 bool GpuBenchmarking::SendMessageToMicroBenchmark(
836 v8::Local
<v8::Object
> message
) {
837 GpuBenchmarkingContext context
;
838 if (!context
.Init(true))
841 scoped_ptr
<V8ValueConverter
> converter
=
842 make_scoped_ptr(V8ValueConverter::create());
843 v8::Local
<v8::Context
> v8_context
=
844 context
.web_frame()->mainWorldScriptContext();
845 scoped_ptr
<base::Value
> value
=
846 make_scoped_ptr(converter
->FromV8Value(message
, v8_context
));
848 return context
.compositor()->SendMessageToMicroBenchmark(id
, value
.Pass());
851 bool GpuBenchmarking::HasGpuProcess() {
852 GpuChannelHost
* gpu_channel
= RenderThreadImpl::current()->GetGpuChannel();
853 return !!gpu_channel
;
856 } // namespace content