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_scroll_gesture_params.h"
18 #include "content/common/input/synthetic_tap_gesture_params.h"
19 #include "content/public/renderer/render_thread.h"
20 #include "content/public/renderer/v8_value_converter.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::Handle
<v8::Function
> callback
,
146 v8::Handle
<v8::Context
> context
)
147 : isolate_(isolate
) {
148 callback_
.Reset(isolate_
, callback
);
149 context_
.Reset(isolate_
, context
);
152 v8::Isolate
* isolate() {
156 v8::Handle
<v8::Function
> GetCallback() {
157 return v8::Local
<v8::Function
>::New(isolate_
, callback_
);
160 v8::Handle
<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::Handle
<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::Handle
<v8::Value
> value
= converter
->ToV8Value(result
.get(), context
);
256 v8::Handle
<v8::Value
> argv
[] = { value
};
258 frame
->callFunctionEvenIfScriptDisabled(
259 callback_and_context
->GetCallback(),
260 v8::Object::New(isolate
),
266 void OnSnapshotCompleted(CallbackAndContext
* callback_and_context
,
267 const gfx::Size
& size
,
268 const std::vector
<unsigned char>& png
) {
269 v8::Isolate
* isolate
= callback_and_context
->isolate();
270 v8::HandleScope
scope(isolate
);
271 v8::Handle
<v8::Context
> context
= callback_and_context
->GetContext();
272 v8::Context::Scope
context_scope(context
);
273 WebLocalFrame
* frame
= WebLocalFrame::frameForContext(context
);
275 v8::Handle
<v8::Value
> result
;
277 if (!size
.IsEmpty()) {
278 v8::Handle
<v8::Object
> result_object
;
279 result_object
= v8::Object::New(isolate
);
281 result_object
->Set(v8::String::NewFromUtf8(isolate
, "width"),
282 v8::Number::New(isolate
, size
.width()));
283 result_object
->Set(v8::String::NewFromUtf8(isolate
, "height"),
284 v8::Number::New(isolate
, size
.height()));
286 std::string base64_png
;
288 base::StringPiece(reinterpret_cast<const char*>(&*png
.begin()),
292 result_object
->Set(v8::String::NewFromUtf8(isolate
, "data"),
293 v8::String::NewFromUtf8(isolate
,
295 v8::String::kNormalString
,
298 result
= result_object
;
300 result
= v8::Null(isolate
);
303 v8::Handle
<v8::Value
> argv
[] = {result
};
305 frame
->callFunctionEvenIfScriptDisabled(
306 callback_and_context
->GetCallback(), v8::Object::New(isolate
), 1, argv
);
310 void OnSyntheticGestureCompleted(CallbackAndContext
* callback_and_context
) {
311 v8::Isolate
* isolate
= callback_and_context
->isolate();
312 v8::HandleScope
scope(isolate
);
313 v8::Handle
<v8::Context
> context
= callback_and_context
->GetContext();
314 v8::Context::Scope
context_scope(context
);
315 WebLocalFrame
* frame
= WebLocalFrame::frameForContext(context
);
317 frame
->callFunctionEvenIfScriptDisabled(
318 callback_and_context
->GetCallback(), v8::Object::New(isolate
), 0, NULL
);
322 bool BeginSmoothScroll(v8::Isolate
* isolate
,
323 int pixels_to_scroll
,
324 v8::Handle
<v8::Function
> callback
,
325 int gesture_source_type
,
326 const std::string
& direction
,
327 int speed_in_pixels_s
,
331 GpuBenchmarkingContext context
;
332 if (!context
.Init(false))
335 scoped_refptr
<CallbackAndContext
> callback_and_context
=
336 new CallbackAndContext(
337 isolate
, callback
, context
.web_frame()->mainWorldScriptContext());
339 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
340 new SyntheticSmoothScrollGestureParams
);
342 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
343 float page_scale_factor
= context
.web_view()->pageScaleFactor();
345 if (gesture_source_type
< 0 ||
346 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
349 gesture_params
->gesture_source_type
=
350 static_cast<SyntheticGestureParams::GestureSourceType
>(
351 gesture_source_type
);
353 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
354 gesture_params
->prevent_fling
= prevent_fling
;
356 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
357 start_y
* page_scale_factor
);
359 int distance_length
= pixels_to_scroll
* page_scale_factor
;
360 gfx::Vector2d distance
;
361 if (direction
== "down")
362 distance
.set_y(-distance_length
);
363 else if (direction
== "up")
364 distance
.set_y(distance_length
);
365 else if (direction
== "right")
366 distance
.set_x(-distance_length
);
367 else if (direction
== "left")
368 distance
.set_x(distance_length
);
372 gesture_params
->distances
.push_back(distance
);
374 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
375 // progress, we will leak the callback and context. This needs to be fixed,
377 context
.render_view_impl()->QueueSyntheticGesture(
378 gesture_params
.Pass(),
379 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
386 gin::WrapperInfo
GpuBenchmarking::kWrapperInfo
= {gin::kEmbedderNativeGin
};
389 void GpuBenchmarking::Install(blink::WebFrame
* frame
) {
390 v8::Isolate
* isolate
= blink::mainThreadIsolate();
391 v8::HandleScope
handle_scope(isolate
);
392 v8::Handle
<v8::Context
> context
= frame
->mainWorldScriptContext();
393 if (context
.IsEmpty())
396 v8::Context::Scope
context_scope(context
);
398 gin::Handle
<GpuBenchmarking
> controller
=
399 gin::CreateHandle(isolate
, new GpuBenchmarking());
400 if (controller
.IsEmpty())
403 v8::Handle
<v8::Object
> chrome
= GetOrCreateChromeObject(isolate
,
405 chrome
->Set(gin::StringToV8(isolate
, "gpuBenchmarking"), controller
.ToV8());
408 GpuBenchmarking::GpuBenchmarking() {
411 GpuBenchmarking::~GpuBenchmarking() {
414 gin::ObjectTemplateBuilder
GpuBenchmarking::GetObjectTemplateBuilder(
415 v8::Isolate
* isolate
) {
416 return gin::Wrappable
<GpuBenchmarking
>::GetObjectTemplateBuilder(isolate
)
417 .SetMethod("setNeedsDisplayOnAllLayers",
418 &GpuBenchmarking::SetNeedsDisplayOnAllLayers
)
419 .SetMethod("setRasterizeOnlyVisibleContent",
420 &GpuBenchmarking::SetRasterizeOnlyVisibleContent
)
421 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture
)
422 .SetValue("DEFAULT_INPUT", 0)
423 .SetValue("TOUCH_INPUT", 1)
424 .SetValue("MOUSE_INPUT", 2)
425 .SetMethod("gestureSourceTypeSupported",
426 &GpuBenchmarking::GestureSourceTypeSupported
)
427 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy
)
428 .SetMethod("swipe", &GpuBenchmarking::Swipe
)
429 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce
)
430 // TODO(dominikg): Remove once JS interface changes have rolled into
432 .SetValue("newPinchInterface", true)
433 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy
)
434 .SetMethod("tap", &GpuBenchmarking::Tap
)
435 .SetMethod("beginWindowSnapshotPNG",
436 &GpuBenchmarking::BeginWindowSnapshotPNG
)
437 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache
)
438 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark
)
439 .SetMethod("sendMessageToMicroBenchmark",
440 &GpuBenchmarking::SendMessageToMicroBenchmark
)
441 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess
);
444 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
445 GpuBenchmarkingContext context
;
446 if (!context
.Init(true))
449 context
.compositor()->SetNeedsDisplayOnAllLayers();
452 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
453 GpuBenchmarkingContext context
;
454 if (!context
.Init(true))
457 context
.compositor()->SetRasterizeOnlyVisibleContent();
460 void GpuBenchmarking::PrintToSkPicture(v8::Isolate
* isolate
,
461 const std::string
& dirname
) {
462 GpuBenchmarkingContext context
;
463 if (!context
.Init(true))
466 const cc::Layer
* root_layer
= context
.compositor()->GetRootLayer();
470 base::FilePath dirpath
= base::FilePath::FromUTF8Unsafe(dirname
);
471 if (!base::CreateDirectory(dirpath
) ||
472 !base::PathIsWritable(dirpath
)) {
473 std::string
msg("Path is not writable: ");
474 msg
.append(dirpath
.MaybeAsASCII());
475 isolate
->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
476 isolate
, msg
.c_str(), v8::String::kNormalString
, msg
.length())));
480 SkPictureSerializer
serializer(dirpath
);
481 serializer
.Serialize(root_layer
);
484 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type
) {
485 if (gesture_source_type
< 0 ||
486 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
490 return SyntheticGestureParams::IsGestureSourceTypeSupported(
491 static_cast<SyntheticGestureParams::GestureSourceType
>(
492 gesture_source_type
));
495 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments
* args
) {
496 GpuBenchmarkingContext context
;
497 if (!context
.Init(true))
500 float page_scale_factor
= context
.web_view()->pageScaleFactor();
501 blink::WebRect rect
= context
.render_view_impl()->windowRect();
503 int pixels_to_scroll
= 0;
504 v8::Handle
<v8::Function
> callback
;
505 int start_x
= rect
.width
/ (page_scale_factor
* 2);
506 int start_y
= rect
.height
/ (page_scale_factor
* 2);
507 int gesture_source_type
= 0; // DEFAULT_INPUT
508 std::string direction
= "down";
509 int speed_in_pixels_s
= 800;
511 if (!GetOptionalArg(args
, &pixels_to_scroll
) ||
512 !GetOptionalArg(args
, &callback
) ||
513 !GetOptionalArg(args
, &start_x
) ||
514 !GetOptionalArg(args
, &start_y
) ||
515 !GetOptionalArg(args
, &gesture_source_type
) ||
516 !GetOptionalArg(args
, &direction
) ||
517 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
521 return BeginSmoothScroll(args
->isolate(),
532 bool GpuBenchmarking::Swipe(gin::Arguments
* args
) {
533 GpuBenchmarkingContext context
;
534 if (!context
.Init(true))
537 float page_scale_factor
= context
.web_view()->pageScaleFactor();
538 blink::WebRect rect
= context
.render_view_impl()->windowRect();
540 std::string direction
= "up";
541 int pixels_to_scroll
= 0;
542 v8::Handle
<v8::Function
> callback
;
543 int start_x
= rect
.width
/ (page_scale_factor
* 2);
544 int start_y
= rect
.height
/ (page_scale_factor
* 2);
545 int speed_in_pixels_s
= 800;
547 if (!GetOptionalArg(args
, &direction
) ||
548 !GetOptionalArg(args
, &pixels_to_scroll
) ||
549 !GetOptionalArg(args
, &callback
) ||
550 !GetOptionalArg(args
, &start_x
) ||
551 !GetOptionalArg(args
, &start_y
) ||
552 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
556 return BeginSmoothScroll(args
->isolate(),
567 bool GpuBenchmarking::ScrollBounce(gin::Arguments
* args
) {
568 GpuBenchmarkingContext context
;
569 if (!context
.Init(false))
572 float page_scale_factor
= context
.web_view()->pageScaleFactor();
573 blink::WebRect rect
= context
.render_view_impl()->windowRect();
575 std::string direction
= "down";
576 int distance_length
= 0;
577 int overscroll_length
= 0;
578 int repeat_count
= 1;
579 v8::Handle
<v8::Function
> callback
;
580 int start_x
= rect
.width
/ (page_scale_factor
* 2);
581 int start_y
= rect
.height
/ (page_scale_factor
* 2);
582 int speed_in_pixels_s
= 800;
584 if (!GetOptionalArg(args
, &direction
) ||
585 !GetOptionalArg(args
, &distance_length
) ||
586 !GetOptionalArg(args
, &overscroll_length
) ||
587 !GetOptionalArg(args
, &repeat_count
) ||
588 !GetOptionalArg(args
, &callback
) ||
589 !GetOptionalArg(args
, &start_x
) ||
590 !GetOptionalArg(args
, &start_y
) ||
591 !GetOptionalArg(args
, &speed_in_pixels_s
)) {
595 scoped_refptr
<CallbackAndContext
> callback_and_context
=
596 new CallbackAndContext(args
->isolate(),
598 context
.web_frame()->mainWorldScriptContext());
600 scoped_ptr
<SyntheticSmoothScrollGestureParams
> gesture_params(
601 new SyntheticSmoothScrollGestureParams
);
603 gesture_params
->speed_in_pixels_s
= speed_in_pixels_s
;
605 gesture_params
->anchor
.SetPoint(start_x
* page_scale_factor
,
606 start_y
* page_scale_factor
);
608 distance_length
*= page_scale_factor
;
609 overscroll_length
*= page_scale_factor
;
610 gfx::Vector2d distance
;
611 gfx::Vector2d overscroll
;
612 if (direction
== "down") {
613 distance
.set_y(-distance_length
);
614 overscroll
.set_y(overscroll_length
);
615 } else if (direction
== "up") {
616 distance
.set_y(distance_length
);
617 overscroll
.set_y(-overscroll_length
);
618 } else if (direction
== "right") {
619 distance
.set_x(-distance_length
);
620 overscroll
.set_x(overscroll_length
);
621 } else if (direction
== "left") {
622 distance
.set_x(distance_length
);
623 overscroll
.set_x(-overscroll_length
);
628 for (int i
= 0; i
< repeat_count
; i
++) {
629 gesture_params
->distances
.push_back(distance
);
630 gesture_params
->distances
.push_back(-distance
+ overscroll
);
633 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
634 // progress, we will leak the callback and context. This needs to be fixed,
636 context
.render_view_impl()->QueueSyntheticGesture(
637 gesture_params
.Pass(),
638 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
643 bool GpuBenchmarking::PinchBy(gin::Arguments
* args
) {
644 GpuBenchmarkingContext context
;
645 if (!context
.Init(false))
651 v8::Handle
<v8::Function
> callback
;
652 int relative_pointer_speed_in_pixels_s
= 800;
655 if (!GetArg(args
, &scale_factor
) ||
656 !GetArg(args
, &anchor_x
) ||
657 !GetArg(args
, &anchor_y
) ||
658 !GetOptionalArg(args
, &callback
) ||
659 !GetOptionalArg(args
, &relative_pointer_speed_in_pixels_s
)) {
663 scoped_ptr
<SyntheticPinchGestureParams
> gesture_params(
664 new SyntheticPinchGestureParams
);
666 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
667 float page_scale_factor
= context
.web_view()->pageScaleFactor();
669 gesture_params
->scale_factor
= scale_factor
;
670 gesture_params
->anchor
.SetPoint(anchor_x
* page_scale_factor
,
671 anchor_y
* page_scale_factor
);
672 gesture_params
->relative_pointer_speed_in_pixels_s
=
673 relative_pointer_speed_in_pixels_s
;
675 scoped_refptr
<CallbackAndContext
> callback_and_context
=
676 new CallbackAndContext(args
->isolate(),
678 context
.web_frame()->mainWorldScriptContext());
681 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
682 // progress, we will leak the callback and context. This needs to be fixed,
684 context
.render_view_impl()->QueueSyntheticGesture(
685 gesture_params
.Pass(),
686 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
691 bool GpuBenchmarking::Tap(gin::Arguments
* args
) {
692 GpuBenchmarkingContext context
;
693 if (!context
.Init(false))
698 v8::Handle
<v8::Function
> callback
;
699 int duration_ms
= 50;
700 int gesture_source_type
= 0; // DEFAULT_INPUT
702 if (!GetArg(args
, &position_x
) ||
703 !GetArg(args
, &position_y
) ||
704 !GetOptionalArg(args
, &callback
) ||
705 !GetOptionalArg(args
, &duration_ms
) ||
706 !GetOptionalArg(args
, &gesture_source_type
)) {
710 scoped_ptr
<SyntheticTapGestureParams
> gesture_params(
711 new SyntheticTapGestureParams
);
713 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
714 float page_scale_factor
= context
.web_view()->pageScaleFactor();
716 gesture_params
->position
.SetPoint(position_x
* page_scale_factor
,
717 position_y
* page_scale_factor
);
718 gesture_params
->duration_ms
= duration_ms
;
720 if (gesture_source_type
< 0 ||
721 gesture_source_type
> SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX
) {
724 gesture_params
->gesture_source_type
=
725 static_cast<SyntheticGestureParams::GestureSourceType
>(
726 gesture_source_type
);
728 scoped_refptr
<CallbackAndContext
> callback_and_context
=
729 new CallbackAndContext(args
->isolate(),
731 context
.web_frame()->mainWorldScriptContext());
733 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
734 // progress, we will leak the callback and context. This needs to be fixed,
736 context
.render_view_impl()->QueueSyntheticGesture(
737 gesture_params
.Pass(),
738 base::Bind(&OnSyntheticGestureCompleted
, callback_and_context
));
743 void GpuBenchmarking::BeginWindowSnapshotPNG(
744 v8::Isolate
* isolate
,
745 v8::Handle
<v8::Function
> callback
) {
746 GpuBenchmarkingContext context
;
747 if (!context
.Init(false))
750 scoped_refptr
<CallbackAndContext
> callback_and_context
=
751 new CallbackAndContext(isolate
,
753 context
.web_frame()->mainWorldScriptContext());
755 context
.render_view_impl()->GetWindowSnapshot(
756 base::Bind(&OnSnapshotCompleted
, callback_and_context
));
759 void GpuBenchmarking::ClearImageCache() {
760 WebImageCache::clear();
763 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments
* args
) {
764 GpuBenchmarkingContext context
;
765 if (!context
.Init(true))
769 v8::Handle
<v8::Function
> callback
;
770 v8::Handle
<v8::Object
> arguments
;
772 if (!GetArg(args
, &name
) || !GetArg(args
, &callback
) ||
773 !GetOptionalArg(args
, &arguments
)) {
777 scoped_refptr
<CallbackAndContext
> callback_and_context
=
778 new CallbackAndContext(args
->isolate(),
780 context
.web_frame()->mainWorldScriptContext());
782 scoped_ptr
<V8ValueConverter
> converter
=
783 make_scoped_ptr(V8ValueConverter::create());
784 v8::Handle
<v8::Context
> v8_context
= callback_and_context
->GetContext();
785 scoped_ptr
<base::Value
> value
=
786 make_scoped_ptr(converter
->FromV8Value(arguments
, v8_context
));
788 return context
.compositor()->ScheduleMicroBenchmark(
791 base::Bind(&OnMicroBenchmarkCompleted
, callback_and_context
));
794 bool GpuBenchmarking::SendMessageToMicroBenchmark(
796 v8::Handle
<v8::Object
> message
) {
797 GpuBenchmarkingContext context
;
798 if (!context
.Init(true))
801 scoped_ptr
<V8ValueConverter
> converter
=
802 make_scoped_ptr(V8ValueConverter::create());
803 v8::Handle
<v8::Context
> v8_context
=
804 context
.web_frame()->mainWorldScriptContext();
805 scoped_ptr
<base::Value
> value
=
806 make_scoped_ptr(converter
->FromV8Value(message
, v8_context
));
808 return context
.compositor()->SendMessageToMicroBenchmark(id
, value
.Pass());
811 bool GpuBenchmarking::HasGpuProcess() {
812 GpuChannelHost
* gpu_channel
= RenderThreadImpl::current()->GetGpuChannel();
813 return !!gpu_channel
;
816 } // namespace content