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/SkStream.h"
38 #include "ui/gfx/codec/png_codec.h"
39 #include "v8/include/v8.h"
41 using blink::WebCanvas;
42 using blink::WebLocalFrame;
43 using blink::WebImageCache;
44 using blink::WebPrivatePtr;
52 // offset parameter is deprecated/ignored, and will be remove from the
53 // signature in a future skia release. <reed@google.com>
54 SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
55 SkPixelRef* pr = bm.pixelRef();
57 SkData* data = pr->refEncodedData();
61 std::vector<unsigned char> vector;
62 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
63 return SkData::NewWithCopy(&vector.front(), vector.size());
68 class SkPictureSerializer {
70 explicit SkPictureSerializer(const base::FilePath& dirpath)
73 // Let skia register known effect subclasses. This basically enables
74 // reflection on those subclasses required for picture serialization.
75 SkiaBenchmarking::Initialize();
78 // Recursively serializes the layer tree.
79 // Each layer in the tree is serialized into a separate skp file
80 // in the given directory.
81 void Serialize(const cc::Layer* layer) {
82 const cc::LayerList& children = layer->children();
83 for (size_t i = 0; i < children.size(); ++i) {
84 Serialize(children[i].get());
87 skia::RefPtr<SkPicture> picture = layer->GetPicture();
91 // Serialize picture to file.
92 // TODO(alokp): Note that for this to work Chrome needs to be launched with
93 // --no-sandbox command-line flag. Get rid of this limitation.
95 std::string filename = "layer_" + base::IntToString(layer_id_++) + ".skp";
96 std::string filepath = dirpath_.AppendASCII(filename).MaybeAsASCII();
97 DCHECK(!filepath.empty());
98 SkFILEWStream file(filepath.c_str());
99 DCHECK(file.isValid());
100 picture->serialize(&file, &EncodeBitmapToData);
104 base::FilePath dirpath_;
108 template <typename T>
109 bool GetArg(gin::Arguments* args, T* value) {
110 if (!args->GetNext(value)) {
118 bool GetArg(gin::Arguments* args, int* value) {
120 bool ret = GetArg(args, &number);
125 template <typename T>
126 bool GetOptionalArg(gin::Arguments* args, T* value) {
127 if (args->PeekNext().IsEmpty())
129 if (args->PeekNext()->IsUndefined()) {
133 return GetArg(args, value);
136 class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
138 CallbackAndContext(v8::Isolate* isolate,
139 v8::Handle<v8::Function> callback,
140 v8::Handle<v8::Context> context)
141 : isolate_(isolate) {
142 callback_.Reset(isolate_, callback);
143 context_.Reset(isolate_, context);
146 v8::Isolate* isolate() {
150 v8::Handle<v8::Function> GetCallback() {
151 return v8::Local<v8::Function>::New(isolate_, callback_);
154 v8::Handle<v8::Context> GetContext() {
155 return v8::Local<v8::Context>::New(isolate_, context_);
159 friend class base::RefCounted<CallbackAndContext>;
161 virtual ~CallbackAndContext() {
166 v8::Isolate* isolate_;
167 v8::Persistent<v8::Function> callback_;
168 v8::Persistent<v8::Context> context_;
169 DISALLOW_COPY_AND_ASSIGN(CallbackAndContext);
172 class GpuBenchmarkingContext {
174 GpuBenchmarkingContext()
177 render_view_impl_(NULL),
180 bool Init(bool init_compositor) {
181 web_frame_ = WebLocalFrame::frameForCurrentContext();
185 web_view_ = web_frame_->view();
191 render_view_impl_ = RenderViewImpl::FromWebView(web_view_);
192 if (!render_view_impl_) {
198 if (!init_compositor)
201 compositor_ = render_view_impl_->compositor();
205 render_view_impl_ = NULL;
212 WebLocalFrame* web_frame() const {
213 DCHECK(web_frame_ != NULL);
216 WebView* web_view() const {
217 DCHECK(web_view_ != NULL);
220 RenderViewImpl* render_view_impl() const {
221 DCHECK(render_view_impl_ != NULL);
222 return render_view_impl_;
224 RenderWidgetCompositor* compositor() const {
225 DCHECK(compositor_ != NULL);
230 WebLocalFrame* web_frame_;
232 RenderViewImpl* render_view_impl_;
233 RenderWidgetCompositor* compositor_;
235 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
238 void OnMicroBenchmarkCompleted(
239 CallbackAndContext* callback_and_context,
240 scoped_ptr<base::Value> result) {
241 v8::Isolate* isolate = callback_and_context->isolate();
242 v8::HandleScope scope(isolate);
243 v8::Handle<v8::Context> context = callback_and_context->GetContext();
244 v8::Context::Scope context_scope(context);
245 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
247 scoped_ptr<V8ValueConverter> converter =
248 make_scoped_ptr(V8ValueConverter::create());
249 v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
250 v8::Handle<v8::Value> argv[] = { value };
252 frame->callFunctionEvenIfScriptDisabled(
253 callback_and_context->GetCallback(),
254 v8::Object::New(isolate),
260 void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
261 const gfx::Size& size,
262 const std::vector<unsigned char>& png) {
263 v8::Isolate* isolate = callback_and_context->isolate();
264 v8::HandleScope scope(isolate);
265 v8::Handle<v8::Context> context = callback_and_context->GetContext();
266 v8::Context::Scope context_scope(context);
267 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
269 v8::Handle<v8::Value> result;
271 if (!size.IsEmpty()) {
272 v8::Handle<v8::Object> result_object;
273 result_object = v8::Object::New(isolate);
275 result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
276 v8::Number::New(isolate, size.width()));
277 result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
278 v8::Number::New(isolate, size.height()));
280 std::string base64_png;
282 base::StringPiece(reinterpret_cast<const char*>(&*png.begin()),
286 result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
287 v8::String::NewFromUtf8(isolate,
289 v8::String::kNormalString,
292 result = result_object;
294 result = v8::Null(isolate);
297 v8::Handle<v8::Value> argv[] = {result};
299 frame->callFunctionEvenIfScriptDisabled(
300 callback_and_context->GetCallback(), v8::Object::New(isolate), 1, argv);
304 void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
305 v8::Isolate* isolate = callback_and_context->isolate();
306 v8::HandleScope scope(isolate);
307 v8::Handle<v8::Context> context = callback_and_context->GetContext();
308 v8::Context::Scope context_scope(context);
309 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
311 frame->callFunctionEvenIfScriptDisabled(
312 callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
316 bool BeginSmoothScroll(v8::Isolate* isolate,
317 int pixels_to_scroll,
318 v8::Handle<v8::Function> callback,
319 int gesture_source_type,
320 const std::string& direction,
321 int speed_in_pixels_s,
325 GpuBenchmarkingContext context;
326 if (!context.Init(false))
329 scoped_refptr<CallbackAndContext> callback_and_context =
330 new CallbackAndContext(
331 isolate, callback, context.web_frame()->mainWorldScriptContext());
333 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
334 new SyntheticSmoothScrollGestureParams);
336 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
337 float page_scale_factor = context.web_view()->pageScaleFactor();
339 if (gesture_source_type < 0 ||
340 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
343 gesture_params->gesture_source_type =
344 static_cast<SyntheticGestureParams::GestureSourceType>(
345 gesture_source_type);
347 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
348 gesture_params->prevent_fling = prevent_fling;
350 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
351 start_y * page_scale_factor);
353 int distance_length = pixels_to_scroll * page_scale_factor;
354 gfx::Vector2d distance;
355 if (direction == "down")
356 distance.set_y(-distance_length);
357 else if (direction == "up")
358 distance.set_y(distance_length);
359 else if (direction == "right")
360 distance.set_x(-distance_length);
361 else if (direction == "left")
362 distance.set_x(distance_length);
366 gesture_params->distances.push_back(distance);
368 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
369 // progress, we will leak the callback and context. This needs to be fixed,
371 context.render_view_impl()->QueueSyntheticGesture(
372 gesture_params.Pass(),
373 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
380 gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
383 void GpuBenchmarking::Install(blink::WebFrame* frame) {
384 v8::Isolate* isolate = blink::mainThreadIsolate();
385 v8::HandleScope handle_scope(isolate);
386 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
387 if (context.IsEmpty())
390 v8::Context::Scope context_scope(context);
392 gin::Handle<GpuBenchmarking> controller =
393 gin::CreateHandle(isolate, new GpuBenchmarking());
394 if (controller.IsEmpty())
397 v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
399 chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
402 GpuBenchmarking::GpuBenchmarking() {
405 GpuBenchmarking::~GpuBenchmarking() {
408 gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
409 v8::Isolate* isolate) {
410 return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
411 .SetMethod("setNeedsDisplayOnAllLayers",
412 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
413 .SetMethod("setRasterizeOnlyVisibleContent",
414 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
415 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
416 .SetValue("DEFAULT_INPUT", 0)
417 .SetValue("TOUCH_INPUT", 1)
418 .SetValue("MOUSE_INPUT", 2)
419 .SetMethod("gestureSourceTypeSupported",
420 &GpuBenchmarking::GestureSourceTypeSupported)
421 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
422 .SetMethod("swipe", &GpuBenchmarking::Swipe)
423 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
424 // TODO(dominikg): Remove once JS interface changes have rolled into
426 .SetValue("newPinchInterface", true)
427 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
428 .SetMethod("tap", &GpuBenchmarking::Tap)
429 .SetMethod("beginWindowSnapshotPNG",
430 &GpuBenchmarking::BeginWindowSnapshotPNG)
431 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
432 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
433 .SetMethod("sendMessageToMicroBenchmark",
434 &GpuBenchmarking::SendMessageToMicroBenchmark)
435 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
438 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
439 GpuBenchmarkingContext context;
440 if (!context.Init(true))
443 context.compositor()->SetNeedsDisplayOnAllLayers();
446 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
447 GpuBenchmarkingContext context;
448 if (!context.Init(true))
451 context.compositor()->SetRasterizeOnlyVisibleContent();
454 void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
455 const std::string& dirname) {
456 GpuBenchmarkingContext context;
457 if (!context.Init(true))
460 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
464 base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
465 if (!base::CreateDirectory(dirpath) ||
466 !base::PathIsWritable(dirpath)) {
467 std::string msg("Path is not writable: ");
468 msg.append(dirpath.MaybeAsASCII());
469 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
470 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
474 SkPictureSerializer serializer(dirpath);
475 serializer.Serialize(root_layer);
478 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
479 if (gesture_source_type < 0 ||
480 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
484 return SyntheticGestureParams::IsGestureSourceTypeSupported(
485 static_cast<SyntheticGestureParams::GestureSourceType>(
486 gesture_source_type));
489 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
490 GpuBenchmarkingContext context;
491 if (!context.Init(true))
494 float page_scale_factor = context.web_view()->pageScaleFactor();
495 blink::WebRect rect = context.render_view_impl()->windowRect();
497 int pixels_to_scroll = 0;
498 v8::Handle<v8::Function> callback;
499 int start_x = rect.width / (page_scale_factor * 2);
500 int start_y = rect.height / (page_scale_factor * 2);
501 int gesture_source_type = 0; // DEFAULT_INPUT
502 std::string direction = "down";
503 int speed_in_pixels_s = 800;
505 if (!GetOptionalArg(args, &pixels_to_scroll) ||
506 !GetOptionalArg(args, &callback) ||
507 !GetOptionalArg(args, &start_x) ||
508 !GetOptionalArg(args, &start_y) ||
509 !GetOptionalArg(args, &gesture_source_type) ||
510 !GetOptionalArg(args, &direction) ||
511 !GetOptionalArg(args, &speed_in_pixels_s)) {
515 return BeginSmoothScroll(args->isolate(),
526 bool GpuBenchmarking::Swipe(gin::Arguments* args) {
527 GpuBenchmarkingContext context;
528 if (!context.Init(true))
531 float page_scale_factor = context.web_view()->pageScaleFactor();
532 blink::WebRect rect = context.render_view_impl()->windowRect();
534 std::string direction = "up";
535 int pixels_to_scroll = 0;
536 v8::Handle<v8::Function> callback;
537 int start_x = rect.width / (page_scale_factor * 2);
538 int start_y = rect.height / (page_scale_factor * 2);
539 int speed_in_pixels_s = 800;
541 if (!GetOptionalArg(args, &direction) ||
542 !GetOptionalArg(args, &pixels_to_scroll) ||
543 !GetOptionalArg(args, &callback) ||
544 !GetOptionalArg(args, &start_x) ||
545 !GetOptionalArg(args, &start_y) ||
546 !GetOptionalArg(args, &speed_in_pixels_s)) {
550 return BeginSmoothScroll(args->isolate(),
561 bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
562 GpuBenchmarkingContext context;
563 if (!context.Init(false))
566 float page_scale_factor = context.web_view()->pageScaleFactor();
567 blink::WebRect rect = context.render_view_impl()->windowRect();
569 std::string direction = "down";
570 int distance_length = 0;
571 int overscroll_length = 0;
572 int repeat_count = 1;
573 v8::Handle<v8::Function> callback;
574 int start_x = rect.width / (page_scale_factor * 2);
575 int start_y = rect.height / (page_scale_factor * 2);
576 int speed_in_pixels_s = 800;
578 if (!GetOptionalArg(args, &direction) ||
579 !GetOptionalArg(args, &distance_length) ||
580 !GetOptionalArg(args, &overscroll_length) ||
581 !GetOptionalArg(args, &repeat_count) ||
582 !GetOptionalArg(args, &callback) ||
583 !GetOptionalArg(args, &start_x) ||
584 !GetOptionalArg(args, &start_y) ||
585 !GetOptionalArg(args, &speed_in_pixels_s)) {
589 scoped_refptr<CallbackAndContext> callback_and_context =
590 new CallbackAndContext(args->isolate(),
592 context.web_frame()->mainWorldScriptContext());
594 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
595 new SyntheticSmoothScrollGestureParams);
597 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
599 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
600 start_y * page_scale_factor);
602 distance_length *= page_scale_factor;
603 overscroll_length *= page_scale_factor;
604 gfx::Vector2d distance;
605 gfx::Vector2d overscroll;
606 if (direction == "down") {
607 distance.set_y(-distance_length);
608 overscroll.set_y(overscroll_length);
609 } else if (direction == "up") {
610 distance.set_y(distance_length);
611 overscroll.set_y(-overscroll_length);
612 } else if (direction == "right") {
613 distance.set_x(-distance_length);
614 overscroll.set_x(overscroll_length);
615 } else if (direction == "left") {
616 distance.set_x(distance_length);
617 overscroll.set_x(-overscroll_length);
622 for (int i = 0; i < repeat_count; i++) {
623 gesture_params->distances.push_back(distance);
624 gesture_params->distances.push_back(-distance + overscroll);
627 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
628 // progress, we will leak the callback and context. This needs to be fixed,
630 context.render_view_impl()->QueueSyntheticGesture(
631 gesture_params.Pass(),
632 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
637 bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
638 GpuBenchmarkingContext context;
639 if (!context.Init(false))
645 v8::Handle<v8::Function> callback;
646 int relative_pointer_speed_in_pixels_s = 800;
649 if (!GetArg(args, &scale_factor) ||
650 !GetArg(args, &anchor_x) ||
651 !GetArg(args, &anchor_y) ||
652 !GetOptionalArg(args, &callback) ||
653 !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
657 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
658 new SyntheticPinchGestureParams);
660 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
661 float page_scale_factor = context.web_view()->pageScaleFactor();
663 gesture_params->scale_factor = scale_factor;
664 gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
665 anchor_y * page_scale_factor);
666 gesture_params->relative_pointer_speed_in_pixels_s =
667 relative_pointer_speed_in_pixels_s;
669 scoped_refptr<CallbackAndContext> callback_and_context =
670 new CallbackAndContext(args->isolate(),
672 context.web_frame()->mainWorldScriptContext());
675 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
676 // progress, we will leak the callback and context. This needs to be fixed,
678 context.render_view_impl()->QueueSyntheticGesture(
679 gesture_params.Pass(),
680 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
685 bool GpuBenchmarking::Tap(gin::Arguments* args) {
686 GpuBenchmarkingContext context;
687 if (!context.Init(false))
692 v8::Handle<v8::Function> callback;
693 int duration_ms = 50;
694 int gesture_source_type = 0; // DEFAULT_INPUT
696 if (!GetArg(args, &position_x) ||
697 !GetArg(args, &position_y) ||
698 !GetOptionalArg(args, &callback) ||
699 !GetOptionalArg(args, &duration_ms) ||
700 !GetOptionalArg(args, &gesture_source_type)) {
704 scoped_ptr<SyntheticTapGestureParams> gesture_params(
705 new SyntheticTapGestureParams);
707 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
708 float page_scale_factor = context.web_view()->pageScaleFactor();
710 gesture_params->position.SetPoint(position_x * page_scale_factor,
711 position_y * page_scale_factor);
712 gesture_params->duration_ms = duration_ms;
714 if (gesture_source_type < 0 ||
715 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
718 gesture_params->gesture_source_type =
719 static_cast<SyntheticGestureParams::GestureSourceType>(
720 gesture_source_type);
722 scoped_refptr<CallbackAndContext> callback_and_context =
723 new CallbackAndContext(args->isolate(),
725 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 void GpuBenchmarking::BeginWindowSnapshotPNG(
738 v8::Isolate* isolate,
739 v8::Handle<v8::Function> callback) {
740 GpuBenchmarkingContext context;
741 if (!context.Init(false))
744 scoped_refptr<CallbackAndContext> callback_and_context =
745 new CallbackAndContext(isolate,
747 context.web_frame()->mainWorldScriptContext());
749 context.render_view_impl()->GetWindowSnapshot(
750 base::Bind(&OnSnapshotCompleted, callback_and_context));
753 void GpuBenchmarking::ClearImageCache() {
754 WebImageCache::clear();
757 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
758 GpuBenchmarkingContext context;
759 if (!context.Init(true))
763 v8::Handle<v8::Function> callback;
764 v8::Handle<v8::Object> arguments;
766 if (!GetArg(args, &name) || !GetArg(args, &callback) ||
767 !GetOptionalArg(args, &arguments)) {
771 scoped_refptr<CallbackAndContext> callback_and_context =
772 new CallbackAndContext(args->isolate(),
774 context.web_frame()->mainWorldScriptContext());
776 scoped_ptr<V8ValueConverter> converter =
777 make_scoped_ptr(V8ValueConverter::create());
778 v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
779 scoped_ptr<base::Value> value =
780 make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
782 return context.compositor()->ScheduleMicroBenchmark(
785 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
788 bool GpuBenchmarking::SendMessageToMicroBenchmark(
790 v8::Handle<v8::Object> message) {
791 GpuBenchmarkingContext context;
792 if (!context.Init(true))
795 scoped_ptr<V8ValueConverter> converter =
796 make_scoped_ptr(V8ValueConverter::create());
797 v8::Handle<v8::Context> v8_context =
798 context.web_frame()->mainWorldScriptContext();
799 scoped_ptr<base::Value> value =
800 make_scoped_ptr(converter->FromV8Value(message, v8_context));
802 return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
805 bool GpuBenchmarking::HasGpuProcess() {
806 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
807 return !!gpu_channel;
810 } // namespace content