IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / renderer / gpu / gpu_benchmarking_extension.cc
blobb5399fb1f38e60bad79f1dab29177ae6f16e9c5b
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"
7 #include <string>
9 #include "base/base64.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.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/browser_rendering_stats.h"
16 #include "content/common/gpu/gpu_rendering_stats.h"
17 #include "content/common/input/synthetic_gesture_params.h"
18 #include "content/common/input/synthetic_pinch_gesture_params.h"
19 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
20 #include "content/common/input/synthetic_tap_gesture_params.h"
21 #include "content/public/renderer/render_thread.h"
22 #include "content/public/renderer/v8_value_converter.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 "third_party/WebKit/public/web/WebFrame.h"
28 #include "third_party/WebKit/public/web/WebImageCache.h"
29 #include "third_party/WebKit/public/web/WebView.h"
30 #include "third_party/skia/include/core/SkData.h"
31 #include "third_party/skia/include/core/SkGraphics.h"
32 #include "third_party/skia/include/core/SkPicture.h"
33 #include "third_party/skia/include/core/SkPixelRef.h"
34 #include "third_party/skia/include/core/SkStream.h"
35 #include "ui/gfx/codec/png_codec.h"
36 #include "v8/include/v8.h"
37 #include "webkit/renderer/compositor_bindings/web_rendering_stats_impl.h"
39 using blink::WebCanvas;
40 using blink::WebFrame;
41 using blink::WebImageCache;
42 using blink::WebPrivatePtr;
43 using blink::WebRenderingStatsImpl;
44 using blink::WebSize;
45 using blink::WebView;
47 const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking";
49 // offset parameter is deprecated/ignored, and will be remove from the
50 // signature in a future skia release. <reed@google.com>
51 static SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
52 SkPixelRef* pr = bm.pixelRef();
53 if (pr != NULL) {
54 SkData* data = pr->refEncodedData();
55 if (data != NULL)
56 return data;
58 std::vector<unsigned char> vector;
59 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
60 return SkData::NewWithCopy(&vector.front() , vector.size());
62 return NULL;
65 namespace {
67 class SkPictureSerializer {
68 public:
69 explicit SkPictureSerializer(const base::FilePath& dirpath)
70 : dirpath_(dirpath),
71 layer_id_(0) {
72 // Let skia register known effect subclasses. This basically enables
73 // reflection on those subclasses required for picture serialization.
74 content::SkiaBenchmarkingExtension::InitSkGraphics();
77 // Recursively serializes the layer tree.
78 // Each layer in the tree is serialized into a separate skp file
79 // in the given directory.
80 void Serialize(const cc::Layer* layer) {
81 const cc::LayerList& children = layer->children();
82 for (size_t i = 0; i < children.size(); ++i) {
83 Serialize(children[i].get());
86 skia::RefPtr<SkPicture> picture = layer->GetPicture();
87 if (!picture)
88 return;
90 // Serialize picture to file.
91 // TODO(alokp): Note that for this to work Chrome needs to be launched with
92 // --no-sandbox command-line flag. Get rid of this limitation.
93 // CRBUG: 139640.
94 std::string filename = "layer_" + base::IntToString(layer_id_++) + ".skp";
95 std::string filepath = dirpath_.AppendASCII(filename).MaybeAsASCII();
96 DCHECK(!filepath.empty());
97 SkFILEWStream file(filepath.c_str());
98 DCHECK(file.isValid());
99 picture->serialize(&file, &EncodeBitmapToData);
102 private:
103 base::FilePath dirpath_;
104 int layer_id_;
107 class RenderingStatsEnumerator : public cc::RenderingStats::Enumerator {
108 public:
109 RenderingStatsEnumerator(v8::Isolate* isolate,
110 v8::Handle<v8::Object> stats_object)
111 : isolate(isolate), stats_object(stats_object) {}
113 virtual void AddInt64(const char* name, int64 value) OVERRIDE {
114 stats_object->Set(v8::String::NewFromUtf8(isolate, name),
115 v8::Number::New(isolate, value));
118 virtual void AddDouble(const char* name, double value) OVERRIDE {
119 stats_object->Set(v8::String::NewFromUtf8(isolate, name),
120 v8::Number::New(isolate, value));
123 virtual void AddInt(const char* name, int value) OVERRIDE {
124 stats_object->Set(v8::String::NewFromUtf8(isolate, name),
125 v8::Integer::New(isolate, value));
128 virtual void AddTimeDeltaInSecondsF(const char* name,
129 const base::TimeDelta& value) OVERRIDE {
130 stats_object->Set(v8::String::NewFromUtf8(isolate, name),
131 v8::Number::New(isolate, value.InSecondsF()));
134 private:
135 v8::Isolate* isolate;
136 v8::Handle<v8::Object> stats_object;
139 } // namespace
141 namespace content {
143 namespace {
145 class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
146 public:
147 CallbackAndContext(v8::Isolate* isolate,
148 v8::Handle<v8::Function> callback,
149 v8::Handle<v8::Context> context)
150 : isolate_(isolate) {
151 callback_.Reset(isolate_, callback);
152 context_.Reset(isolate_, context);
155 v8::Isolate* isolate() {
156 return isolate_;
159 v8::Handle<v8::Function> GetCallback() {
160 return v8::Local<v8::Function>::New(isolate_, callback_);
163 v8::Handle<v8::Context> GetContext() {
164 return v8::Local<v8::Context>::New(isolate_, context_);
167 private:
168 friend class base::RefCounted<CallbackAndContext>;
170 virtual ~CallbackAndContext() {
171 callback_.Reset();
172 context_.Reset();
175 v8::Isolate* isolate_;
176 v8::Persistent<v8::Function> callback_;
177 v8::Persistent<v8::Context> context_;
178 DISALLOW_COPY_AND_ASSIGN(CallbackAndContext);
181 class GpuBenchmarkingContext {
182 public:
183 GpuBenchmarkingContext()
184 : web_frame_(NULL),
185 web_view_(NULL),
186 render_view_impl_(NULL),
187 compositor_(NULL) {}
189 bool Init(bool init_compositor) {
190 web_frame_ = WebFrame::frameForCurrentContext();
191 if (!web_frame_)
192 return false;
194 web_view_ = web_frame_->view();
195 if (!web_view_) {
196 web_frame_ = NULL;
197 return false;
200 render_view_impl_ = RenderViewImpl::FromWebView(web_view_);
201 if (!render_view_impl_) {
202 web_frame_ = NULL;
203 web_view_ = NULL;
204 return false;
207 if (!init_compositor)
208 return true;
210 compositor_ = render_view_impl_->compositor();
211 if (!compositor_) {
212 web_frame_ = NULL;
213 web_view_ = NULL;
214 render_view_impl_ = NULL;
215 return false;
218 return true;
221 WebFrame* web_frame() const {
222 DCHECK(web_frame_ != NULL);
223 return web_frame_;
225 WebView* web_view() const {
226 DCHECK(web_view_ != NULL);
227 return web_view_;
229 RenderViewImpl* render_view_impl() const {
230 DCHECK(render_view_impl_ != NULL);
231 return render_view_impl_;
233 RenderWidgetCompositor* compositor() const {
234 DCHECK(compositor_ != NULL);
235 return compositor_;
238 private:
239 WebFrame* web_frame_;
240 WebView* web_view_;
241 RenderViewImpl* render_view_impl_;
242 RenderWidgetCompositor* compositor_;
244 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
247 } // namespace
249 class GpuBenchmarkingWrapper : public v8::Extension {
250 public:
251 GpuBenchmarkingWrapper() :
252 v8::Extension(kGpuBenchmarkingExtensionName,
253 "if (typeof(chrome) == 'undefined') {"
254 " chrome = {};"
255 "};"
256 "if (typeof(chrome.gpuBenchmarking) == 'undefined') {"
257 " chrome.gpuBenchmarking = {};"
258 "};"
259 "chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers = function() {"
260 " native function SetNeedsDisplayOnAllLayers();"
261 " return SetNeedsDisplayOnAllLayers();"
262 "};"
263 "chrome.gpuBenchmarking.setRasterizeOnlyVisibleContent = function() {"
264 " native function SetRasterizeOnlyVisibleContent();"
265 " return SetRasterizeOnlyVisibleContent();"
266 "};"
267 "chrome.gpuBenchmarking.renderingStats = function() {"
268 " native function GetRenderingStats();"
269 " return GetRenderingStats();"
270 "};"
271 "chrome.gpuBenchmarking.gpuRenderingStats = function() {"
272 " native function GetGpuRenderingStats();"
273 " return GetGpuRenderingStats();"
274 "};"
275 "chrome.gpuBenchmarking.printToSkPicture = function(dirname) {"
276 " native function PrintToSkPicture();"
277 " return PrintToSkPicture(dirname);"
278 "};"
279 "chrome.gpuBenchmarking.DEFAULT_INPUT = 0;"
280 "chrome.gpuBenchmarking.TOUCH_INPUT = 1;"
281 "chrome.gpuBenchmarking.MOUSE_INPUT = 2;"
282 "chrome.gpuBenchmarking.smoothScrollBy = "
283 " function(pixels_to_scroll, opt_callback, opt_start_x,"
284 " opt_start_y, opt_gesture_source_type,"
285 " opt_direction, opt_speed_in_pixels_s) {"
286 " pixels_to_scroll = pixels_to_scroll || 0;"
287 " callback = opt_callback || function() { };"
288 " gesture_source_type = opt_gesture_source_type ||"
289 " chrome.gpuBenchmarking.DEFAULT_INPUT;"
290 " direction = opt_direction || 'down';"
291 " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
292 " native function BeginSmoothScroll();"
293 " return BeginSmoothScroll(pixels_to_scroll, callback,"
294 " gesture_source_type, direction,"
295 " speed_in_pixels_s, true,"
296 " opt_start_x, opt_start_y);"
297 "};"
298 "chrome.gpuBenchmarking.smoothScrollBySendsTouch = function() {"
299 " native function SmoothScrollSendsTouch();"
300 " return SmoothScrollSendsTouch();"
301 "};"
302 "chrome.gpuBenchmarking.swipe = "
303 " function(direction, distance, opt_callback,"
304 " opt_start_x, opt_start_y,"
305 " opt_speed_in_pixels_s) {"
306 " direction = direction || 'up';"
307 " distance = distance || 0;"
308 " callback = opt_callback || function() { };"
309 " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
310 " native function BeginSmoothScroll();"
311 " return BeginSmoothScroll(-distance, callback,"
312 " chrome.gpuBenchmarking.TOUCH_INPUT,"
313 " direction, speed_in_pixels_s, false,"
314 " opt_start_x, opt_start_y);"
315 "};"
316 "chrome.gpuBenchmarking.pinchBy = "
317 " function(zoom_in, pixels_to_cover, anchor_x, anchor_y,"
318 " opt_callback, opt_relative_pointer_speed_in_pixels_s) {"
319 " callback = opt_callback || function() { };"
320 " relative_pointer_speed_in_pixels_s ="
321 " opt_relative_pointer_speed_in_pixels_s || 800;"
322 " native function BeginPinch();"
323 " return BeginPinch(zoom_in, pixels_to_cover,"
324 " anchor_x, anchor_y, callback,"
325 " relative_pointer_speed_in_pixels_s);"
326 "};"
327 "chrome.gpuBenchmarking.tap = "
328 " function(position_x, position_y, opt_callback, opt_duration_ms,"
329 " opt_gesture_source_type) {"
330 " callback = opt_callback || function() { };"
331 " duration_ms = opt_duration_ms || 0;"
332 " gesture_source_type = opt_gesture_source_type ||"
333 " chrome.gpuBenchmarking.DEFAULT_INPUT;"
334 " native function BeginTap();"
335 " return BeginTap(position_x, position_y, callback, duration_ms,"
336 " gesture_source_type);"
337 "};"
338 "chrome.gpuBenchmarking.beginWindowSnapshotPNG = function(callback) {"
339 " native function BeginWindowSnapshotPNG();"
340 " BeginWindowSnapshotPNG(callback);"
341 "};"
342 "chrome.gpuBenchmarking.clearImageCache = function() {"
343 " native function ClearImageCache();"
344 " ClearImageCache();"
345 "};"
346 "chrome.gpuBenchmarking.runMicroBenchmark ="
347 " function(name, callback, opt_arguments) {"
348 " arguments = opt_arguments || {};"
349 " native function RunMicroBenchmark();"
350 " return RunMicroBenchmark(name, callback, arguments);"
351 "};"
352 "chrome.gpuBenchmarking.hasGpuProcess = function() {"
353 " native function HasGpuProcess();"
354 " return HasGpuProcess();"
355 "};") {}
357 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
358 v8::Isolate* isolate,
359 v8::Handle<v8::String> name) OVERRIDE {
360 if (name->Equals(
361 v8::String::NewFromUtf8(isolate, "SetNeedsDisplayOnAllLayers")))
362 return v8::FunctionTemplate::New(isolate, SetNeedsDisplayOnAllLayers);
363 if (name->Equals(
364 v8::String::NewFromUtf8(isolate, "SetRasterizeOnlyVisibleContent")))
365 return v8::FunctionTemplate::New(isolate, SetRasterizeOnlyVisibleContent);
366 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetRenderingStats")))
367 return v8::FunctionTemplate::New(isolate, GetRenderingStats);
368 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetGpuRenderingStats")))
369 return v8::FunctionTemplate::New(isolate, GetGpuRenderingStats);
370 if (name->Equals(v8::String::NewFromUtf8(isolate, "PrintToSkPicture")))
371 return v8::FunctionTemplate::New(isolate, PrintToSkPicture);
372 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginSmoothScroll")))
373 return v8::FunctionTemplate::New(isolate, BeginSmoothScroll);
374 if (name->Equals(
375 v8::String::NewFromUtf8(isolate, "SmoothScrollSendsTouch")))
376 return v8::FunctionTemplate::New(isolate, SmoothScrollSendsTouch);
377 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginPinch")))
378 return v8::FunctionTemplate::New(isolate, BeginPinch);
379 if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginTap")))
380 return v8::FunctionTemplate::New(isolate, BeginTap);
381 if (name->Equals(
382 v8::String::NewFromUtf8(isolate, "BeginWindowSnapshotPNG")))
383 return v8::FunctionTemplate::New(isolate, BeginWindowSnapshotPNG);
384 if (name->Equals(v8::String::NewFromUtf8(isolate, "ClearImageCache")))
385 return v8::FunctionTemplate::New(isolate, ClearImageCache);
386 if (name->Equals(v8::String::NewFromUtf8(isolate, "RunMicroBenchmark")))
387 return v8::FunctionTemplate::New(isolate, RunMicroBenchmark);
388 if (name->Equals(v8::String::NewFromUtf8(isolate, "HasGpuProcess")))
389 return v8::FunctionTemplate::New(isolate, HasGpuProcess);
391 return v8::Handle<v8::FunctionTemplate>();
394 static void SetNeedsDisplayOnAllLayers(
395 const v8::FunctionCallbackInfo<v8::Value>& args) {
396 GpuBenchmarkingContext context;
397 if (!context.Init(true))
398 return;
400 context.compositor()->SetNeedsDisplayOnAllLayers();
403 static void SetRasterizeOnlyVisibleContent(
404 const v8::FunctionCallbackInfo<v8::Value>& args) {
405 GpuBenchmarkingContext context;
406 if (!context.Init(true))
407 return;
409 context.compositor()->SetRasterizeOnlyVisibleContent();
412 static void GetRenderingStats(
413 const v8::FunctionCallbackInfo<v8::Value>& args) {
415 GpuBenchmarkingContext context;
416 if (!context.Init(false))
417 return;
419 WebRenderingStatsImpl stats;
420 context.render_view_impl()->GetRenderingStats(stats);
422 content::GpuRenderingStats gpu_stats;
423 context.render_view_impl()->GetGpuRenderingStats(&gpu_stats);
424 BrowserRenderingStats browser_stats;
425 context.render_view_impl()->GetBrowserRenderingStats(&browser_stats);
426 v8::Handle<v8::Object> stats_object = v8::Object::New(args.GetIsolate());
428 RenderingStatsEnumerator enumerator(args.GetIsolate(), stats_object);
429 stats.rendering_stats.EnumerateFields(&enumerator);
430 gpu_stats.EnumerateFields(&enumerator);
431 browser_stats.EnumerateFields(&enumerator);
433 args.GetReturnValue().Set(stats_object);
436 static void GetGpuRenderingStats(
437 const v8::FunctionCallbackInfo<v8::Value>& args) {
439 GpuBenchmarkingContext context;
440 if (!context.Init(false))
441 return;
443 content::GpuRenderingStats gpu_stats;
444 context.render_view_impl()->GetGpuRenderingStats(&gpu_stats);
446 v8::Isolate* isolate = args.GetIsolate();
447 v8::Handle<v8::Object> stats_object = v8::Object::New(isolate);
448 RenderingStatsEnumerator enumerator(isolate, stats_object);
449 gpu_stats.EnumerateFields(&enumerator);
451 args.GetReturnValue().Set(stats_object);
454 static void PrintToSkPicture(
455 const v8::FunctionCallbackInfo<v8::Value>& args) {
456 if (args.Length() != 1)
457 return;
459 v8::String::Utf8Value dirname(args[0]);
460 if (dirname.length() == 0)
461 return;
463 GpuBenchmarkingContext context;
464 if (!context.Init(true))
465 return;
467 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
468 if (!root_layer)
469 return;
471 base::FilePath dirpath(
472 base::FilePath::StringType(*dirname, *dirname + dirname.length()));
473 if (!base::CreateDirectory(dirpath) ||
474 !base::PathIsWritable(dirpath)) {
475 std::string msg("Path is not writable: ");
476 msg.append(dirpath.MaybeAsASCII());
477 v8::Isolate* isolate = args.GetIsolate();
478 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
479 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
480 return;
483 SkPictureSerializer serializer(dirpath);
484 serializer.Serialize(root_layer);
487 static void OnSyntheticGestureCompleted(
488 CallbackAndContext* callback_and_context) {
489 v8::Isolate* isolate = callback_and_context->isolate();
490 v8::HandleScope scope(isolate);
491 v8::Handle<v8::Context> context = callback_and_context->GetContext();
492 v8::Context::Scope context_scope(context);
493 WebFrame* frame = WebFrame::frameForContext(context);
494 if (frame) {
495 frame->callFunctionEvenIfScriptDisabled(
496 callback_and_context->GetCallback(),
497 v8::Object::New(isolate),
499 NULL);
503 static void SmoothScrollSendsTouch(
504 const v8::FunctionCallbackInfo<v8::Value>& args) {
505 // TODO(epenner): Should other platforms emulate touch events?
506 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
507 args.GetReturnValue().Set(true);
508 #else
509 args.GetReturnValue().Set(false);
510 #endif
513 static void BeginSmoothScroll(
514 const v8::FunctionCallbackInfo<v8::Value>& args) {
515 GpuBenchmarkingContext context;
516 if (!context.Init(false))
517 return;
519 // The last two arguments can be undefined. We check their validity later.
520 int arglen = args.Length();
521 if (arglen < 8 ||
522 !args[0]->IsNumber() ||
523 !args[1]->IsFunction() ||
524 !args[2]->IsNumber() ||
525 !args[3]->IsString() ||
526 !args[4]->IsNumber() ||
527 !args[5]->IsBoolean()) {
528 args.GetReturnValue().Set(false);
529 return;
532 v8::Local<v8::Function> callback_local =
533 v8::Local<v8::Function>::Cast(args[1]);
535 scoped_refptr<CallbackAndContext> callback_and_context =
536 new CallbackAndContext(args.GetIsolate(),
537 callback_local,
538 context.web_frame()->mainWorldScriptContext());
540 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
541 new SyntheticSmoothScrollGestureParams);
543 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
544 float page_scale_factor = context.web_view()->pageScaleFactor();
546 int gesture_source_type = args[2]->IntegerValue();
547 if (gesture_source_type < 0 ||
548 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
549 args.GetReturnValue().Set(false);
550 return;
552 gesture_params->gesture_source_type =
553 static_cast<SyntheticGestureParams::GestureSourceType>(
554 gesture_source_type);
556 int distance = args[0]->IntegerValue() * page_scale_factor;
557 v8::String::Utf8Value direction(args[3]);
558 DCHECK(*direction);
559 std::string direction_str(*direction);
560 if (direction_str == "down")
561 gesture_params->distance.set_y(distance);
562 else if (direction_str == "up")
563 gesture_params->distance.set_y(-distance);
564 else if (direction_str == "right")
565 gesture_params->distance.set_x(distance);
566 else if (direction_str == "left")
567 gesture_params->distance.set_x(-distance);
568 else {
569 args.GetReturnValue().Set(false);
570 return;
573 gesture_params->speed_in_pixels_s = args[4]->IntegerValue();
574 gesture_params->prevent_fling = args[5]->BooleanValue();
576 // Account for the 2 optional arguments, start_x and start_y.
577 if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
578 blink::WebRect rect = context.render_view_impl()->windowRect();
579 gesture_params->anchor.SetPoint(rect.width / 2, rect.height / 2);
580 } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
581 gesture_params->anchor.SetPoint(
582 args[6]->IntegerValue() * page_scale_factor,
583 args[7]->IntegerValue() * page_scale_factor);
584 } else {
585 args.GetReturnValue().Set(false);
586 return;
589 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
590 // progress, we will leak the callback and context. This needs to be fixed,
591 // somehow.
592 context.render_view_impl()->QueueSyntheticGesture(
593 gesture_params.PassAs<SyntheticGestureParams>(),
594 base::Bind(&OnSyntheticGestureCompleted,
595 callback_and_context));
597 args.GetReturnValue().Set(true);
600 static void BeginPinch(
601 const v8::FunctionCallbackInfo<v8::Value>& args) {
602 GpuBenchmarkingContext context;
603 if (!context.Init(false))
604 return;
606 int arglen = args.Length();
607 if (arglen < 6 ||
608 !args[0]->IsBoolean() ||
609 !args[1]->IsNumber() ||
610 !args[2]->IsNumber() ||
611 !args[3]->IsNumber() ||
612 !args[4]->IsFunction() ||
613 !args[5]->IsNumber()) {
614 args.GetReturnValue().Set(false);
615 return;
618 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
619 new SyntheticPinchGestureParams);
621 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
622 float page_scale_factor = context.web_view()->pageScaleFactor();
624 gesture_params->zoom_in = args[0]->BooleanValue();
625 gesture_params->total_num_pixels_covered =
626 args[1]->IntegerValue() * page_scale_factor;
627 gesture_params->anchor.SetPoint(
628 args[2]->IntegerValue() * page_scale_factor,
629 args[3]->IntegerValue() * page_scale_factor);
630 gesture_params->relative_pointer_speed_in_pixels_s =
631 args[5]->IntegerValue();
633 v8::Local<v8::Function> callback_local =
634 v8::Local<v8::Function>::Cast(args[4]);
636 scoped_refptr<CallbackAndContext> callback_and_context =
637 new CallbackAndContext(args.GetIsolate(),
638 callback_local,
639 context.web_frame()->mainWorldScriptContext());
642 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
643 // progress, we will leak the callback and context. This needs to be fixed,
644 // somehow.
645 context.render_view_impl()->QueueSyntheticGesture(
646 gesture_params.PassAs<SyntheticGestureParams>(),
647 base::Bind(&OnSyntheticGestureCompleted,
648 callback_and_context));
650 args.GetReturnValue().Set(true);
653 static void BeginTap(
654 const v8::FunctionCallbackInfo<v8::Value>& args) {
655 GpuBenchmarkingContext context;
656 if (!context.Init(false))
657 return;
659 int arglen = args.Length();
660 if (arglen < 5 ||
661 !args[0]->IsNumber() ||
662 !args[1]->IsNumber() ||
663 !args[2]->IsFunction() ||
664 !args[3]->IsNumber() ||
665 !args[4]->IsNumber()) {
666 args.GetReturnValue().Set(false);
667 return;
670 scoped_ptr<SyntheticTapGestureParams> gesture_params(
671 new SyntheticTapGestureParams);
673 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
674 float page_scale_factor = context.web_view()->pageScaleFactor();
676 gesture_params->position.SetPoint(
677 args[0]->IntegerValue() * page_scale_factor,
678 args[1]->IntegerValue() * page_scale_factor);
679 gesture_params->duration_ms = args[3]->IntegerValue();
681 int gesture_source_type = args[4]->IntegerValue();
682 if (gesture_source_type < 0 ||
683 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
684 args.GetReturnValue().Set(false);
685 return;
687 gesture_params->gesture_source_type =
688 static_cast<SyntheticGestureParams::GestureSourceType>(
689 gesture_source_type);
691 v8::Local<v8::Function> callback_local =
692 v8::Local<v8::Function>::Cast(args[2]);
694 scoped_refptr<CallbackAndContext> callback_and_context =
695 new CallbackAndContext(args.GetIsolate(),
696 callback_local,
697 context.web_frame()->mainWorldScriptContext());
700 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
701 // progress, we will leak the callback and context. This needs to be fixed,
702 // somehow.
703 context.render_view_impl()->QueueSyntheticGesture(
704 gesture_params.PassAs<SyntheticGestureParams>(),
705 base::Bind(&OnSyntheticGestureCompleted,
706 callback_and_context));
708 args.GetReturnValue().Set(true);
711 static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
712 const gfx::Size& size,
713 const std::vector<unsigned char>& png) {
714 v8::Isolate* isolate = callback_and_context->isolate();
715 v8::HandleScope scope(isolate);
716 v8::Handle<v8::Context> context = callback_and_context->GetContext();
717 v8::Context::Scope context_scope(context);
718 WebFrame* frame = WebFrame::frameForContext(context);
719 if (frame) {
721 v8::Handle<v8::Value> result;
723 if(!size.IsEmpty()) {
724 v8::Handle<v8::Object> result_object;
725 result_object = v8::Object::New(isolate);
727 result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
728 v8::Number::New(isolate, size.width()));
729 result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
730 v8::Number::New(isolate, size.height()));
732 std::string base64_png;
733 base::Base64Encode(base::StringPiece(
734 reinterpret_cast<const char*>(&*png.begin()), png.size()),
735 &base64_png);
737 result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
738 v8::String::NewFromUtf8(isolate,
739 base64_png.c_str(),
740 v8::String::kNormalString,
741 base64_png.size()));
743 result = result_object;
744 } else {
745 result = v8::Null(isolate);
748 v8::Handle<v8::Value> argv[] = { result };
750 frame->callFunctionEvenIfScriptDisabled(
751 callback_and_context->GetCallback(),
752 v8::Object::New(isolate),
754 argv);
758 static void BeginWindowSnapshotPNG(
759 const v8::FunctionCallbackInfo<v8::Value>& args) {
760 GpuBenchmarkingContext context;
761 if (!context.Init(false))
762 return;
764 if (!args[0]->IsFunction())
765 return;
767 v8::Local<v8::Function> callback_local =
768 v8::Local<v8::Function>::Cast(args[0]);
770 scoped_refptr<CallbackAndContext> callback_and_context =
771 new CallbackAndContext(args.GetIsolate(),
772 callback_local,
773 context.web_frame()->mainWorldScriptContext());
775 context.render_view_impl()->GetWindowSnapshot(
776 base::Bind(&OnSnapshotCompleted, callback_and_context));
779 static void ClearImageCache(
780 const v8::FunctionCallbackInfo<v8::Value>& args) {
781 WebImageCache::clear();
784 static void OnMicroBenchmarkCompleted(
785 CallbackAndContext* callback_and_context,
786 scoped_ptr<base::Value> result) {
787 v8::Isolate* isolate = callback_and_context->isolate();
788 v8::HandleScope scope(isolate);
789 v8::Handle<v8::Context> context = callback_and_context->GetContext();
790 v8::Context::Scope context_scope(context);
791 WebFrame* frame = WebFrame::frameForContext(context);
792 if (frame) {
793 scoped_ptr<V8ValueConverter> converter =
794 make_scoped_ptr(V8ValueConverter::create());
795 v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
796 v8::Handle<v8::Value> argv[] = { value };
798 frame->callFunctionEvenIfScriptDisabled(
799 callback_and_context->GetCallback(),
800 v8::Object::New(isolate),
802 argv);
806 static void RunMicroBenchmark(
807 const v8::FunctionCallbackInfo<v8::Value>& args) {
808 GpuBenchmarkingContext context;
809 if (!context.Init(true)) {
810 args.GetReturnValue().Set(false);
811 return;
814 if (args.Length() != 3 ||
815 !args[0]->IsString() ||
816 !args[1]->IsFunction() ||
817 !args[2]->IsObject()) {
818 args.GetReturnValue().Set(false);
819 return;
822 v8::Local<v8::Function> callback_local =
823 v8::Local<v8::Function>::Cast(args[1]);
825 scoped_refptr<CallbackAndContext> callback_and_context =
826 new CallbackAndContext(args.GetIsolate(),
827 callback_local,
828 context.web_frame()->mainWorldScriptContext());
830 scoped_ptr<V8ValueConverter> converter =
831 make_scoped_ptr(V8ValueConverter::create());
832 v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
833 scoped_ptr<base::Value> value =
834 make_scoped_ptr(converter->FromV8Value(args[2], v8_context));
836 v8::String::Utf8Value benchmark(args[0]);
837 DCHECK(*benchmark);
838 args.GetReturnValue().Set(context.compositor()->ScheduleMicroBenchmark(
839 std::string(*benchmark),
840 value.Pass(),
841 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context)));
844 static void HasGpuProcess(const v8::FunctionCallbackInfo<v8::Value>& args) {
845 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
846 args.GetReturnValue().Set(!!gpu_channel);
850 v8::Extension* GpuBenchmarkingExtension::Get() {
851 return new GpuBenchmarkingWrapper();
854 } // namespace content