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 v8::Handle
<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::Handle
<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::Handle
<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 scoped_refptr
<CallbackAndContext
> callback_and_context
=
293 new CallbackAndContext(
294 isolate
, callback
, context
.web_frame()->mainWorldScriptContext());
296 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
297 new SyntheticSmoothScrollGestureParams
);
299 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
300 float page_scale_factor
= context
.web_view()->pageScaleFactor();
302 if (gesture_source_type
< 0 ||
303 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
306 gesture_params
->gesture_source_type
=
307 static_cast<SyntheticGestureParams::GestureSourceType
>(
308 gesture_source_type
);
310 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
311 gesture_params
->prevent_fling
= prevent_fling
;
313 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
314 start_y
* page_scale_factor
);
316 float distance_length
= pixels_to_scroll
* page_scale_factor
;
317 gfx::Vector2dF distance
;
318 if (direction
== "down")
319 distance
.set_y(-distance_length
);
320 else if (direction
== "up")
321 distance
.set_y(distance_length
);
322 else if (direction
== "right")
323 distance
.set_x(-distance_length
);
324 else if (direction
== "left")
325 distance
.set_x(distance_length
);
326 else if (direction
== "upleft") {
327 distance
.set_y(distance_length
);
328 distance
.set_x(distance_length
);
329 } else if (direction
== "upright") {
330 distance
.set_y(distance_length
);
331 distance
.set_x(-distance_length
);
332 } else if (direction
== "downleft") {
333 distance
.set_y(-distance_length
);
334 distance
.set_x(distance_length
);
335 } else if (direction
== "downright") {
336 distance
.set_y(-distance_length
);
337 distance
.set_x(-distance_length
);
341 gesture_params
->distances
.push_back(distance
);
343 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
344 // progress, we will leak the callback and context. This needs to be fixed,
346 context
.render_view_impl()->QueueSyntheticGesture(
347 gesture_params
.Pass(),
348 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
353 bool BeginSmoothDrag(v8::Isolate
* isolate
,
358 v8::Handle
<v8::Function
> callback
,
359 int gesture_source_type
,
360 float speed_in_pixels_s
) {
361 GpuBenchmarkingContext context
;
362 if (!context
.Init(false))
364 scoped_refptr
<CallbackAndContext
> callback_and_context
=
365 new CallbackAndContext(isolate
, callback
,
366 context
.web_frame()->mainWorldScriptContext());
368 scoped_ptr
<SyntheticSmoothDragGestureParams
> gesture_params(
369 new SyntheticSmoothDragGestureParams
);
371 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
372 float page_scale_factor
= context
.web_view()->pageScaleFactor();
374 gesture_params
->start_point
.SetPoint(start_x
* page_scale_factor
,
375 start_y
* page_scale_factor
);
376 gfx::PointF
end_point(end_x
* page_scale_factor
,
377 end_y
* page_scale_factor
);
378 gfx::Vector2dF distance
= end_point
- gesture_params
->start_point
;
379 gesture_params
->distances
.push_back(distance
);
380 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
* page_scale_factor
;
381 gesture_params
->gesture_source_type
=
382 static_cast<SyntheticGestureParams::GestureSourceType
>(
383 gesture_source_type
);
385 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
386 // progress, we will leak the callback and context. This needs to be fixed,
388 context
.render_view_impl()->QueueSyntheticGesture(
389 gesture_params
.Pass(),
390 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
397 gin::WrapperInfo
GpuBenchmarking::kWrapperInfo
= {gin::kEmbedderNativeGin
};
400 void GpuBenchmarking::Install(blink::WebFrame
* frame
) {
401 v8::Isolate
* isolate
= blink::mainThreadIsolate();
402 v8::HandleScope
handle_scope(isolate
);
403 v8::Handle
<v8::Context
> context
= frame
->mainWorldScriptContext();
404 if (context
.IsEmpty())
407 v8::Context::Scope
context_scope(context
);
409 gin::Handle
<GpuBenchmarking
> controller
=
410 gin::CreateHandle(isolate
, new GpuBenchmarking());
411 if (controller
.IsEmpty())
414 v8::Handle
<v8::Object
> chrome
= GetOrCreateChromeObject(isolate
,
416 chrome
->Set(gin::StringToV8(isolate
, "gpuBenchmarking"), controller
.ToV8());
419 GpuBenchmarking::GpuBenchmarking() {
422 GpuBenchmarking::~GpuBenchmarking() {
425 gin::ObjectTemplateBuilder
GpuBenchmarking::GetObjectTemplateBuilder(
426 v8::Isolate
* isolate
) {
427 return gin::Wrappable
<GpuBenchmarking
>::GetObjectTemplateBuilder(isolate
)
428 .SetMethod("setNeedsDisplayOnAllLayers",
429 &GpuBenchmarking::SetNeedsDisplayOnAllLayers
)
430 .SetMethod("setRasterizeOnlyVisibleContent",
431 &GpuBenchmarking::SetRasterizeOnlyVisibleContent
)
432 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture
)
433 .SetValue("DEFAULT_INPUT", 0)
434 .SetValue("TOUCH_INPUT", 1)
435 .SetValue("MOUSE_INPUT", 2)
436 .SetMethod("gestureSourceTypeSupported",
437 &GpuBenchmarking::GestureSourceTypeSupported
)
438 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy
)
439 .SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag
)
440 .SetMethod("swipe", &GpuBenchmarking::Swipe
)
441 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce
)
442 // TODO(dominikg): Remove once JS interface changes have rolled into
444 .SetValue("newPinchInterface", true)
445 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy
)
446 .SetMethod("tap", &GpuBenchmarking::Tap
)
447 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache
)
448 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark
)
449 .SetMethod("sendMessageToMicroBenchmark",
450 &GpuBenchmarking::SendMessageToMicroBenchmark
)
451 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess
);
454 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
455 GpuBenchmarkingContext context
;
456 if (!context
.Init(true))
459 context
.compositor()->SetNeedsDisplayOnAllLayers();
462 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
463 GpuBenchmarkingContext context
;
464 if (!context
.Init(true))
467 context
.compositor()->SetRasterizeOnlyVisibleContent();
470 void GpuBenchmarking::PrintToSkPicture(v8::Isolate
* isolate
,
471 const std::string
& dirname
) {
472 GpuBenchmarkingContext context
;
473 if (!context
.Init(true))
476 const cc::Layer
* root_layer
= context
.compositor()->GetRootLayer();
480 base::FilePath dirpath
= base::FilePath::FromUTF8Unsafe(dirname
);
481 if (!base::CreateDirectory(dirpath
) ||
482 !base::PathIsWritable(dirpath
)) {
483 std::string
msg("Path is not writable: ");
484 msg
.append(dirpath
.MaybeAsASCII());
485 isolate
->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
486 isolate
, msg
.c_str(), v8::String::kNormalString
, msg
.length())));
490 SkPictureSerializer
serializer(dirpath
);
491 serializer
.Serialize(root_layer
);
494 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type
) {
495 if (gesture_source_type
< 0 ||
496 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
500 return SyntheticGestureParams::IsGestureSourceTypeSupported(
501 static_cast<SyntheticGestureParams::GestureSourceType
>(
502 gesture_source_type
));
505 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments
* args
) {
506 GpuBenchmarkingContext context
;
507 if (!context
.Init(true))
510 float page_scale_factor
= context
.web_view()->pageScaleFactor();
511 blink::WebRect rect
= context
.render_view_impl()->windowRect();
513 float pixels_to_scroll
= 0;
514 v8::Handle
<v8::Function
> callback
;
515 float start_x
= rect
.width
/ (page_scale_factor
* 2);
516 float start_y
= rect
.height
/ (page_scale_factor
* 2);
517 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
518 std::string direction
= "down";
519 float speed_in_pixels_s
= 800;
521 if (!GetOptionalArg(args
, &pixels_to_scroll
) ||
522 !GetOptionalArg(args
, &callback
) ||
523 !GetOptionalArg(args
, &start_x
) ||
524 !GetOptionalArg(args
, &start_y
) ||
525 !GetOptionalArg(args
, &gesture_source_type
) ||
526 !GetOptionalArg(args
, &direction
) ||
527 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
531 return BeginSmoothScroll(args
->isolate(),
542 bool GpuBenchmarking::SmoothDrag(gin::Arguments
* args
) {
543 GpuBenchmarkingContext context
;
544 if (!context
.Init(true))
551 v8::Handle
<v8::Function
> callback
;
552 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
553 float speed_in_pixels_s
= 800;
555 if (!GetArg(args
, &start_x
) ||
556 !GetArg(args
, &start_y
) ||
557 !GetArg(args
, &end_x
) ||
558 !GetArg(args
, &end_y
) ||
559 !GetOptionalArg(args
, &callback
) ||
560 !GetOptionalArg(args
, &gesture_source_type
) ||
561 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
565 return BeginSmoothDrag(args
->isolate(),
575 bool GpuBenchmarking::Swipe(gin::Arguments
* args
) {
576 GpuBenchmarkingContext context
;
577 if (!context
.Init(true))
580 float page_scale_factor
= context
.web_view()->pageScaleFactor();
581 blink::WebRect rect
= context
.render_view_impl()->windowRect();
583 std::string direction
= "up";
584 float pixels_to_scroll
= 0;
585 v8::Handle
<v8::Function
> callback
;
586 float start_x
= rect
.width
/ (page_scale_factor
* 2);
587 float start_y
= rect
.height
/ (page_scale_factor
* 2);
588 float speed_in_pixels_s
= 800;
590 if (!GetOptionalArg(args
, &direction
) ||
591 !GetOptionalArg(args
, &pixels_to_scroll
) ||
592 !GetOptionalArg(args
, &callback
) ||
593 !GetOptionalArg(args
, &start_x
) ||
594 !GetOptionalArg(args
, &start_y
) ||
595 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
599 return BeginSmoothScroll(args
->isolate(),
610 bool GpuBenchmarking::ScrollBounce(gin::Arguments
* args
) {
611 GpuBenchmarkingContext context
;
612 if (!context
.Init(false))
615 float page_scale_factor
= context
.web_view()->pageScaleFactor();
616 blink::WebRect rect
= context
.render_view_impl()->windowRect();
618 std::string direction
= "down";
619 float distance_length
= 0;
620 float overscroll_length
= 0;
621 int repeat_count
= 1;
622 v8::Handle
<v8::Function
> callback
;
623 float start_x
= rect
.width
/ (page_scale_factor
* 2);
624 float start_y
= rect
.height
/ (page_scale_factor
* 2);
625 float speed_in_pixels_s
= 800;
627 if (!GetOptionalArg(args
, &direction
) ||
628 !GetOptionalArg(args
, &distance_length
) ||
629 !GetOptionalArg(args
, &overscroll_length
) ||
630 !GetOptionalArg(args
, &repeat_count
) ||
631 !GetOptionalArg(args
, &callback
) ||
632 !GetOptionalArg(args
, &start_x
) ||
633 !GetOptionalArg(args
, &start_y
) ||
634 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
638 scoped_refptr
<CallbackAndContext
> callback_and_context
=
639 new CallbackAndContext(args
->isolate(),
641 context
.web_frame()->mainWorldScriptContext());
643 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
644 new SyntheticSmoothScrollGestureParams
);
646 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
648 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
649 start_y
* page_scale_factor
);
651 distance_length
*= page_scale_factor
;
652 overscroll_length
*= page_scale_factor
;
653 gfx::Vector2dF distance
;
654 gfx::Vector2dF overscroll
;
655 if (direction
== "down") {
656 distance
.set_y(-distance_length
);
657 overscroll
.set_y(overscroll_length
);
658 } else if (direction
== "up") {
659 distance
.set_y(distance_length
);
660 overscroll
.set_y(-overscroll_length
);
661 } else if (direction
== "right") {
662 distance
.set_x(-distance_length
);
663 overscroll
.set_x(overscroll_length
);
664 } else if (direction
== "left") {
665 distance
.set_x(distance_length
);
666 overscroll
.set_x(-overscroll_length
);
671 for (int i
= 0; i
< repeat_count
; i
++) {
672 gesture_params
->distances
.push_back(distance
);
673 gesture_params
->distances
.push_back(-distance
+ overscroll
);
676 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
677 // progress, we will leak the callback and context. This needs to be fixed,
679 context
.render_view_impl()->QueueSyntheticGesture(
680 gesture_params
.Pass(),
681 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
686 bool GpuBenchmarking::PinchBy(gin::Arguments
* args
) {
687 GpuBenchmarkingContext context
;
688 if (!context
.Init(false))
694 v8::Handle
<v8::Function
> callback
;
695 float relative_pointer_speed_in_pixels_s
= 800;
698 if (!GetArg(args
, &scale_factor
) ||
699 !GetArg(args
, &anchor_x
) ||
700 !GetArg(args
, &anchor_y
) ||
701 !GetOptionalArg(args
, &callback
) ||
702 !GetOptionalArg(args
, &relative_pointer_speed_in_pixels_s
)) {
706 scoped_ptr
<SyntheticPinchGestureParams
> gesture_params(
707 new SyntheticPinchGestureParams
);
709 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
710 float page_scale_factor
= context
.web_view()->pageScaleFactor();
712 gesture_params
->scale_factor
= scale_factor
;
713 gesture_params
->anchor
.SetPoint(anchor_x
* page_scale_factor
,
714 anchor_y
* page_scale_factor
);
715 gesture_params
->relative_pointer_speed_in_pixels_s
=
716 relative_pointer_speed_in_pixels_s
;
718 scoped_refptr
<CallbackAndContext
> callback_and_context
=
719 new CallbackAndContext(args
->isolate(),
721 context
.web_frame()->mainWorldScriptContext());
724 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
725 // progress, we will leak the callback and context. This needs to be fixed,
727 context
.render_view_impl()->QueueSyntheticGesture(
728 gesture_params
.Pass(),
729 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
734 bool GpuBenchmarking::Tap(gin::Arguments
* args
) {
735 GpuBenchmarkingContext context
;
736 if (!context
.Init(false))
741 v8::Handle
<v8::Function
> callback
;
742 int duration_ms
= 50;
743 int gesture_source_type
= SyntheticGestureParams::DEFAULT_INPUT
;
745 if (!GetArg(args
, &position_x
) ||
746 !GetArg(args
, &position_y
) ||
747 !GetOptionalArg(args
, &callback
) ||
748 !GetOptionalArg(args
, &duration_ms
) ||
749 !GetOptionalArg(args
, &gesture_source_type
)) {
753 scoped_ptr
<SyntheticTapGestureParams
> gesture_params(
754 new SyntheticTapGestureParams
);
756 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
757 float page_scale_factor
= context
.web_view()->pageScaleFactor();
759 gesture_params
->position
.SetPoint(position_x
* page_scale_factor
,
760 position_y
* page_scale_factor
);
761 gesture_params
->duration_ms
= duration_ms
;
763 if (gesture_source_type
< 0 ||
764 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
767 gesture_params
->gesture_source_type
=
768 static_cast<SyntheticGestureParams::GestureSourceType
>(
769 gesture_source_type
);
771 scoped_refptr
<CallbackAndContext
> callback_and_context
=
772 new CallbackAndContext(args
->isolate(),
774 context
.web_frame()->mainWorldScriptContext());
776 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
777 // progress, we will leak the callback and context. This needs to be fixed,
779 context
.render_view_impl()->QueueSyntheticGesture(
780 gesture_params
.Pass(),
781 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
786 void GpuBenchmarking::ClearImageCache() {
787 WebImageCache::clear();
790 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments
* args
) {
791 GpuBenchmarkingContext context
;
792 if (!context
.Init(true))
796 v8::Handle
<v8::Function
> callback
;
797 v8::Handle
<v8::Object
> arguments
;
799 if (!GetArg(args
, &name
) || !GetArg(args
, &callback
) ||
800 !GetOptionalArg(args
, &arguments
)) {
804 scoped_refptr
<CallbackAndContext
> callback_and_context
=
805 new CallbackAndContext(args
->isolate(),
807 context
.web_frame()->mainWorldScriptContext());
809 scoped_ptr
<V8ValueConverter
> converter
=
810 make_scoped_ptr(V8ValueConverter::create());
811 v8::Handle
<v8::Context
> v8_context
= callback_and_context
->GetContext();
812 scoped_ptr
<base::Value
> value
=
813 make_scoped_ptr(converter
->FromV8Value(arguments
, v8_context
));
815 return context
.compositor()->ScheduleMicroBenchmark(
818 base::Bind(&OnMicroBenchmarkCompleted
, callback_and_context
));
821 bool GpuBenchmarking::SendMessageToMicroBenchmark(
823 v8::Handle
<v8::Object
> message
) {
824 GpuBenchmarkingContext context
;
825 if (!context
.Init(true))
828 scoped_ptr
<V8ValueConverter
> converter
=
829 make_scoped_ptr(V8ValueConverter::create());
830 v8::Handle
<v8::Context
> v8_context
=
831 context
.web_frame()->mainWorldScriptContext();
832 scoped_ptr
<base::Value
> value
=
833 make_scoped_ptr(converter
->FromV8Value(message
, v8_context
));
835 return context
.compositor()->SendMessageToMicroBenchmark(id
, value
.Pass());
838 bool GpuBenchmarking::HasGpuProcess() {
839 GpuChannelHost
* gpu_channel
= RenderThreadImpl::current()->GetGpuChannel();
840 return !!gpu_channel
;
843 } // namespace content