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::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() {
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_
);
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::Handle
<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::Handle
<v8::Value
> value
= converter
->ToV8Value(result
.get(), context
);
257 #ifdef WEB_FRAME_USES_V8_LOCAL
258 v8::Local
<v8::Value
> argv
[] = {value
};
260 v8::Handle
<v8::Value
> argv
[] = { value
};
262 frame
->callFunctionEvenIfScriptDisabled(
263 callback_and_context
->GetCallback(),
264 v8::Object::New(isolate
),
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
);
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
,
291 GpuBenchmarkingContext context
;
292 if (!context
.Init(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
) {
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
);
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,
349 context
.render_view_impl()->QueueSyntheticGesture(
350 gesture_params
.Pass(),
351 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
356 bool BeginSmoothDrag(v8::Isolate
* isolate
,
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))
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,
391 context
.render_view_impl()->QueueSyntheticGesture(
392 gesture_params
.Pass(),
393 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
400 gin::WrapperInfo
GpuBenchmarking::kWrapperInfo
= {gin::kEmbedderNativeGin
};
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())
410 v8::Context::Scope
context_scope(context
);
412 gin::Handle
<GpuBenchmarking
> controller
=
413 gin::CreateHandle(isolate
, new GpuBenchmarking());
414 if (controller
.IsEmpty())
417 v8::Handle
<v8::Object
> chrome
= GetOrCreateChromeObject(isolate
,
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
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))
462 context
.compositor()->SetNeedsDisplayOnAllLayers();
465 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
466 GpuBenchmarkingContext context
;
467 if (!context
.Init(true))
470 context
.compositor()->SetRasterizeOnlyVisibleContent();
473 void GpuBenchmarking::PrintToSkPicture(v8::Isolate
* isolate
,
474 const std::string
& dirname
) {
475 GpuBenchmarkingContext context
;
476 if (!context
.Init(true))
479 const cc::Layer
* root_layer
= context
.compositor()->GetRootLayer();
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())));
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
) {
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))
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
)) {
534 return BeginSmoothScroll(args
->isolate(),
545 bool GpuBenchmarking::SmoothDrag(gin::Arguments
* args
) {
546 GpuBenchmarkingContext context
;
547 if (!context
.Init(true))
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
)) {
568 return BeginSmoothDrag(args
->isolate(),
578 bool GpuBenchmarking::Swipe(gin::Arguments
* args
) {
579 GpuBenchmarkingContext context
;
580 if (!context
.Init(true))
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
)) {
602 return BeginSmoothScroll(args
->isolate(),
613 bool GpuBenchmarking::ScrollBounce(gin::Arguments
* args
) {
614 GpuBenchmarkingContext context
;
615 if (!context
.Init(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
)) {
641 scoped_refptr
<CallbackAndContext
> callback_and_context
=
642 new CallbackAndContext(args
->isolate(),
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
);
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,
682 context
.render_view_impl()->QueueSyntheticGesture(
683 gesture_params
.Pass(),
684 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
689 bool GpuBenchmarking::PinchBy(gin::Arguments
* args
) {
690 GpuBenchmarkingContext context
;
691 if (!context
.Init(false))
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
)) {
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(),
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,
730 context
.render_view_impl()->QueueSyntheticGesture(
731 gesture_params
.Pass(),
732 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
737 bool GpuBenchmarking::Tap(gin::Arguments
* args
) {
738 GpuBenchmarkingContext context
;
739 if (!context
.Init(false))
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
)) {
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
) {
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(),
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,
782 context
.render_view_impl()->QueueSyntheticGesture(
783 gesture_params
.Pass(),
784 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
789 void GpuBenchmarking::ClearImageCache() {
790 WebImageCache::clear();
793 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments
* args
) {
794 GpuBenchmarkingContext context
;
795 if (!context
.Init(true))
799 v8::Handle
<v8::Function
> callback
;
800 v8::Handle
<v8::Object
> arguments
;
802 if (!GetArg(args
, &name
) || !GetArg(args
, &callback
) ||
803 !GetOptionalArg(args
, &arguments
)) {
807 scoped_refptr
<CallbackAndContext
> callback_and_context
=
808 new CallbackAndContext(args
->isolate(),
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(
821 base::Bind(&OnMicroBenchmarkCompleted
, callback_and_context
));
824 bool GpuBenchmarking::SendMessageToMicroBenchmark(
826 v8::Handle
<v8::Object
> message
) {
827 GpuBenchmarkingContext context
;
828 if (!context
.Init(true))
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