1a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// found in the LICENSE file. 4a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 5a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "content/renderer/skia_benchmarking_extension.h" 6a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/base64.h" 8fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "base/time/time.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/base/math_util.h" 11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "cc/resources/picture.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/renderer/v8_value_converter.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/render_thread_impl.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/arguments.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/handle.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/object_template_builder.h" 17fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch#include "skia/ext/benchmarking_canvas.h" 189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "third_party/WebKit/public/platform/WebArrayBuffer.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebArrayBufferConverter.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebKit.h" 22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h" 23a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "third_party/skia/include/core/SkColorPriv.h" 24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "third_party/skia/include/core/SkGraphics.h" 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "third_party/skia/include/core/SkStream.h" 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/skia/src/utils/debugger/SkDebugCanvas.h" 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "third_party/skia/src/utils/debugger/SkDrawCommand.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/rect_conversions.h" 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/skia_util.h" 30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "v8/include/v8.h" 31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content { 34a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::Value> ParsePictureArg(v8::Isolate* isolate, 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> arg) { 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<content::V8ValueConverter> converter( 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::V8ValueConverter::create()); 4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return scoped_ptr<base::Value>( 42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) converter->FromV8Value(arg, isolate->GetCurrentContext())); 4358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<cc::Picture> ParsePictureStr(v8::Isolate* isolate, 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> arg) { 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<base::Value> picture_value = ParsePictureArg(isolate, arg); 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!picture_value) 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return NULL; 5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return cc::Picture::CreateFromSkpValue(picture_value.get()); 5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<cc::Picture> ParsePictureHash(v8::Isolate* isolate, 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> arg) { 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<base::Value> picture_value = ParsePictureArg(isolate, arg); 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!picture_value) 5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NULL; 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return cc::Picture::CreateFromValue(picture_value.get()); 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::WrapperInfo SkiaBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin}; 64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkiaBenchmarking::Install(blink::WebFrame* frame) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate = blink::mainThreadIsolate(); 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (context.IsEmpty()) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Context::Scope context_scope(context); 74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gin::Handle<SkiaBenchmarking> controller = 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gin::CreateHandle(isolate, new SkiaBenchmarking()); 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (controller.IsEmpty()) 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> global = context->Global(); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> chrome = 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) global->Get(gin::StringToV8(isolate, "chrome"))->ToObject(); 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (chrome.IsEmpty()) { 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chrome = v8::Object::New(isolate); 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) global->Set(gin::StringToV8(isolate, "chrome"), chrome); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chrome->Set(gin::StringToV8(isolate, "skiaBenchmarking"), controller.ToV8()); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkiaBenchmarking::Initialize() { 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(RenderThreadImpl::current()); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // FIXME: remove this after Skia updates SkGraphics::Init() to be 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // thread-safe and idempotent. 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static bool skia_initialized = false; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!skia_initialized) { 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(WARNING) << "Enabling unsafe Skia benchmarking extension."; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkGraphics::Init(); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) skia_initialized = true; 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SkiaBenchmarking::SkiaBenchmarking() { 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Initialize(); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SkiaBenchmarking::~SkiaBenchmarking() {} 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::ObjectTemplateBuilder SkiaBenchmarking::GetObjectTemplateBuilder( 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate) { 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return gin::Wrappable<SkiaBenchmarking>::GetObjectTemplateBuilder(isolate) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("rasterize", &SkiaBenchmarking::Rasterize) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("getOps", &SkiaBenchmarking::GetOps) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("getOpTimings", &SkiaBenchmarking::GetOpTimings) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .SetMethod("getInfo", &SkiaBenchmarking::GetInfo); 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkiaBenchmarking::Rasterize(gin::Arguments* args) { 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate = args->isolate(); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (args->PeekNext().IsEmpty()) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> picture_handle; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->GetNext(&picture_handle); 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<cc::Picture> picture = 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ParsePictureHash(isolate, picture_handle); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!picture.get()) 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) double scale = 1.0; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect clip_rect(picture->LayerRect()); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int stop_index = -1; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool overdraw = false; 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) v8::Handle<v8::Context> context = isolate->GetCurrentContext(); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!args->PeekNext().IsEmpty()) { 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> params; 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->GetNext(¶ms); 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<content::V8ValueConverter> converter( 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::V8ValueConverter::create()); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::Value> params_value( 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) converter->FromV8Value(params, context)); 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::DictionaryValue* params_dict = NULL; 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (params_value.get() && params_value->GetAsDictionary(¶ms_dict)) { 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params_dict->GetDouble("scale", &scale); 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params_dict->GetInteger("stop", &stop_index); 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params_dict->GetBoolean("overdraw", &overdraw); 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Value* clip_value = NULL; 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (params_dict->Get("clip", &clip_value)) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cc::MathUtil::FromValue(clip_value, &clip_rect); 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::RectF clip(clip_rect); 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) clip.Intersect(picture->LayerRect()); 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) clip.Scale(scale); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect snapped_clip = gfx::ToEnclosingRect(clip); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkBitmap bitmap; 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!bitmap.tryAllocN32Pixels(snapped_clip.width(), snapped_clip.height())) 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bitmap.eraseARGB(0, 0, 0, 0); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkCanvas canvas(bitmap); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas.translate(SkFloatToScalar(-clip.x()), SkFloatToScalar(-clip.y())); 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas.clipRect(gfx::RectToSkRect(snapped_clip)); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas.scale(scale, scale); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) canvas.translate(picture->LayerRect().x(), picture->LayerRect().y()); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // First, build a debug canvas for the given picture. 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkDebugCanvas debug_canvas(picture->LayerRect().width(), 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) picture->LayerRect().height()); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) picture->Replay(&debug_canvas); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Raster the requested command subset into the bitmap-backed canvas. 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int last_index = debug_canvas.getSize() - 1; 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (last_index >= 0) { 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) debug_canvas.setOverdrawViz(overdraw); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) debug_canvas.drawTo( 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &canvas, 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stop_index < 0 ? last_index : std::min(last_index, stop_index)); 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 184fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blink::WebArrayBuffer buffer = 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blink::WebArrayBuffer::create(bitmap.getSize(), 1); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32* packed_pixels = reinterpret_cast<uint32*>(bitmap.getPixels()); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8* buffer_pixels = reinterpret_cast<uint8*>(buffer.data()); 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Swizzle from native Skia format to RGBA as we copy out. 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < bitmap.getSize(); i += 4) { 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 c = packed_pixels[i >> 2]; 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_pixels[i] = SkGetPackedR32(c); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_pixels[i + 1] = SkGetPackedG32(c); 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_pixels[i + 2] = SkGetPackedB32(c); 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer_pixels[i + 3] = SkGetPackedA32(c); 196fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch } 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> result = v8::Object::New(isolate); 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "width"), 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Number::New(isolate, snapped_clip.width())); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "height"), 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Number::New(isolate, snapped_clip.height())); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "data"), 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) blink::WebArrayBufferConverter::toV8Value( 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) &buffer, context->Global(), isolate)); 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->Return(result); 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkiaBenchmarking::GetOps(gin::Arguments* args) { 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate = args->isolate(); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (args->PeekNext().IsEmpty()) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> picture_handle; 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->GetNext(&picture_handle); 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<cc::Picture> picture = 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ParsePictureHash(isolate, picture_handle); 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!picture.get()) 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect bounds = picture->LayerRect(); 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkDebugCanvas canvas(bounds.width(), bounds.height()); 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) picture->Replay(&canvas); 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Array> result = v8::Array::New(isolate, canvas.getSize()); 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int i = 0; i < canvas.getSize(); ++i) { 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DrawType cmd_type = canvas.getDrawCommandAt(i)->getType(); 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> cmd = v8::Object::New(isolate); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cmd->Set(v8::String::NewFromUtf8(isolate, "cmd_type"), 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Integer::New(isolate, cmd_type)); 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cmd->Set(v8::String::NewFromUtf8(isolate, "cmd_string"), 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::String::NewFromUtf8( 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) isolate, SkDrawCommand::GetCommandString(cmd_type))); 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SkTDArray<SkString*>* info = canvas.getCommandInfo(i); 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(info); 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Local<v8::Array> v8_info = v8::Array::New(isolate, info->count()); 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (int j = 0; j < info->count(); ++j) { 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SkString* info_str = (*info)[j]; 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(info_str); 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8_info->Set(j, v8::String::NewFromUtf8(isolate, info_str->c_str())); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cmd->Set(v8::String::NewFromUtf8(isolate, "info"), v8_info); 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(i, cmd); 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 249a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->Return(result.As<v8::Object>()); 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 252a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkiaBenchmarking::GetOpTimings(gin::Arguments* args) { 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate = args->isolate(); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (args->PeekNext().IsEmpty()) 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> picture_handle; 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->GetNext(&picture_handle); 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<cc::Picture> picture = 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ParsePictureHash(isolate, picture_handle); 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!picture.get()) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) gfx::Rect bounds = picture->LayerRect(); 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Measure the total time by drawing straight into a bitmap-backed canvas. 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SkBitmap bitmap; 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bitmap.allocN32Pixels(bounds.width(), bounds.height()); 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SkCanvas bitmap_canvas(bitmap); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bitmap_canvas.clear(SK_ColorTRANSPARENT); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeTicks t0 = base::TimeTicks::HighResNow(); 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) picture->Replay(&bitmap_canvas); 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::TimeDelta total_time = base::TimeTicks::HighResNow() - t0; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Gather per-op timing info by drawing into a BenchmarkingCanvas. 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) skia::BenchmarkingCanvas benchmarking_canvas(bounds.width(), bounds.height()); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) picture->Replay(&benchmarking_canvas); 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Local<v8::Array> op_times = 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Array::New(isolate, benchmarking_canvas.CommandCount()); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < benchmarking_canvas.CommandCount(); ++i) 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) op_times->Set(i, v8::Number::New(isolate, benchmarking_canvas.GetTime(i))); 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> result = v8::Object::New(isolate); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "total_time"), 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Number::New(isolate, total_time.InMillisecondsF())); 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "cmd_times"), op_times); 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->Return(result); 290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SkiaBenchmarking::GetInfo(gin::Arguments* args) { 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Isolate* isolate = args->isolate(); 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (args->PeekNext().IsEmpty()) 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> picture_handle; 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->GetNext(&picture_handle); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<cc::Picture> picture = 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ParsePictureStr(isolate, picture_handle); 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!picture.get()) 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Object> result = v8::Object::New(isolate); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "width"), 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Number::New(isolate, picture->LayerRect().width())); 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result->Set(v8::String::NewFromUtf8(isolate, "height"), 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Number::New(isolate, picture->LayerRect().height())); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) args->Return(result); 310a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} // namespace content 313