summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/renderer/skia_benchmarking_extension.cc53
-rw-r--r--skia/ext/benchmarking_canvas.cc237
-rw-r--r--skia/ext/benchmarking_canvas.h50
-rw-r--r--skia/skia_chrome.gypi2
-rw-r--r--skia/skia_library.gypi2
5 files changed, 344 insertions, 0 deletions
diff --git a/content/renderer/skia_benchmarking_extension.cc b/content/renderer/skia_benchmarking_extension.cc
index 078b51d..14dfe3b 100644
--- a/content/renderer/skia_benchmarking_extension.cc
+++ b/content/renderer/skia_benchmarking_extension.cc
@@ -4,14 +4,17 @@
#include "content/renderer/skia_benchmarking_extension.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "cc/base/math_util.h"
#include "cc/resources/picture.h"
#include "content/public/renderer/v8_value_converter.h"
+#include "skia/ext/benchmarking_canvas.h"
#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorPriv.h"
+#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkGraphics.h"
#include "third_party/skia/src/utils/debugger/SkDebugCanvas.h"
#include "third_party/skia/src/utils/debugger/SkDrawCommand.h"
@@ -79,6 +82,17 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
" native function GetOps();"
" return GetOps(picture);"
"};"
+ "chrome.skiaBenchmarking.getOpTimings = function(picture) {"
+ " /* "
+ " Returns timing information for the given picture."
+ " @param {Object} picture A json-encoded cc::Picture."
+ " @returns { 'total_time': {Number}, 'cmd_times': [Number, ...] }"
+ " @returns undefined if the arguments are invalid or the picture"
+ " version is not supported."
+ " */"
+ " native function GetOpTimings();"
+ " return GetOpTimings(picture);"
+ "};"
) {
content::SkiaBenchmarkingExtension::InitSkGraphics();
}
@@ -89,6 +103,8 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
return v8::FunctionTemplate::New(Rasterize);
if (name->Equals(v8::String::New("GetOps")))
return v8::FunctionTemplate::New(GetOps);
+ if (name->Equals(v8::String::New("GetOpTimings")))
+ return v8::FunctionTemplate::New(GetOpTimings);
return v8::Handle<v8::FunctionTemplate>();
}
@@ -218,6 +234,43 @@ class SkiaBenchmarkingWrapper : public v8::Extension {
args.GetReturnValue().Set(result);
}
+
+ static void GetOpTimings(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ if (args.Length() != 1)
+ return;
+
+ scoped_refptr<cc::Picture> picture = ParsePictureArg(args[0]);
+ if (!picture.get())
+ return;
+
+ gfx::Rect bounds = picture->LayerRect();
+
+ // Measure the total time by drawing straight into a bitmap-backed canvas.
+ skia::RefPtr<SkDevice> device = skia::AdoptRef(SkNEW_ARGS(SkDevice,
+ (SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height())));
+ SkCanvas bitmap_canvas(device.get());
+ bitmap_canvas.clear(SK_ColorTRANSPARENT);
+ base::TimeTicks t0 = base::TimeTicks::HighResNow();
+ picture->Replay(&bitmap_canvas);
+ base::TimeDelta total_time = base::TimeTicks::HighResNow() - t0;
+
+ // Gather per-op timing info by drawing into a BenchmarkingCanvas.
+ skia::BenchmarkingCanvas benchmarking_canvas(bounds.width(),
+ bounds.height());
+ picture->Replay(&benchmarking_canvas);
+
+ v8::Local<v8::Array> op_times =
+ v8::Array::New(benchmarking_canvas.CommandCount());
+ for (size_t i = 0; i < benchmarking_canvas.CommandCount(); ++i)
+ op_times->Set(i, v8::Number::New(benchmarking_canvas.GetTime(i)));
+
+ v8::Handle<v8::Object> result = v8::Object::New();
+ result->Set(v8::String::New("total_time"),
+ v8::Number::New(total_time.InMillisecondsF()));
+ result->Set(v8::String::New("cmd_times"), op_times);
+
+ args.GetReturnValue().Set(result);
+ }
};
} // namespace
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc
new file mode 100644
index 0000000..6039515
--- /dev/null
+++ b/skia/ext/benchmarking_canvas.cc
@@ -0,0 +1,237 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/containers/hash_tables.h"
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "skia/ext/benchmarking_canvas.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "third_party/skia/include/utils/SkProxyCanvas.h"
+
+namespace skia {
+
+class AutoStamper {
+public:
+ AutoStamper(TimingCanvas* timing_canvas);
+ ~AutoStamper();
+
+private:
+ TimingCanvas* timing_canvas_;
+ base::TimeTicks start_ticks_;
+};
+
+class TimingCanvas : public SkProxyCanvas {
+public:
+ TimingCanvas(int width, int height, const BenchmarkingCanvas* track_canvas)
+ : tracking_canvas_(track_canvas) {
+ skia::RefPtr<SkDevice> device = skia::AdoptRef(
+ SkNEW_ARGS(SkDevice, (SkBitmap::kARGB_8888_Config, width, height)));
+ canvas_ = skia::AdoptRef(SkNEW_ARGS(SkCanvas, (device.get())));
+
+ setProxy(canvas_.get());
+ }
+
+ virtual ~TimingCanvas() {
+ }
+
+ double GetTime(size_t index) {
+ TimingsMap::const_iterator timing_info = timings_map_.find(index);
+ return timing_info != timings_map_.end()
+ ? timing_info->second.InMillisecondsF()
+ : 0.0;
+ }
+
+ // SkCanvas overrides.
+ virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) OVERRIDE {
+ AutoStamper stamper(this);
+ return SkProxyCanvas::save(flags);
+ }
+
+ virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags = kARGB_ClipLayer_SaveFlag) OVERRIDE {
+ AutoStamper stamper(this);
+ return SkProxyCanvas::saveLayer(bounds, paint, flags);
+ }
+
+ virtual void restore() OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::restore();
+ }
+
+ virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
+ bool doAa) OVERRIDE {
+ AutoStamper stamper(this);
+ return SkProxyCanvas::clipRect(rect, op, doAa);
+ }
+
+ virtual bool clipRRect(const SkRRect& rrect, SkRegion::Op op,
+ bool doAa) OVERRIDE {
+ AutoStamper stamper(this);
+ return SkProxyCanvas::clipRRect(rrect, op, doAa);
+ }
+
+ virtual bool clipPath(const SkPath& path, SkRegion::Op op,
+ bool doAa) OVERRIDE {
+ AutoStamper stamper(this);
+ return SkProxyCanvas::clipPath(path, op, doAa);
+ }
+
+ virtual bool clipRegion(const SkRegion& region,
+ SkRegion::Op op = SkRegion::kIntersect_Op) OVERRIDE {
+ AutoStamper stamper(this);
+ return SkProxyCanvas::clipRegion(region, op);
+ }
+
+ virtual void drawPaint(const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawPaint(paint);
+ }
+
+ virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawPoints(mode, count, pts, paint);
+ }
+
+ virtual void drawOval(const SkRect& rect, const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawOval(rect, paint);
+ }
+
+ virtual void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawRect(rect, paint);
+ }
+
+ virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawRRect(rrect, paint);
+ }
+
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawPath(path, paint);
+ }
+
+ virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawBitmap(bitmap, left, top, paint);
+ }
+
+ virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint = NULL) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawBitmapRectToRect(bitmap, src, dst, paint);
+ }
+
+ virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
+ const SkPaint* paint = NULL) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawBitmapMatrix(bitmap, m, paint);
+ }
+
+ virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint = NULL) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawSprite(bitmap, left, top, paint);
+ }
+
+ virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+ SkScalar y, const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawText(text, byteLength, x, y, paint);
+ }
+
+ virtual void drawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[],
+ const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawPosText(text, byteLength, pos, paint);
+ }
+
+ virtual void drawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawPosTextH(text, byteLength, xpos, constY, paint);
+ }
+
+ virtual void drawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawTextOnPath(text, byteLength, path, matrix, paint);
+ }
+
+ virtual void drawPicture(SkPicture& picture) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawPicture(picture);
+ }
+
+ virtual void drawVertices(VertexMode vmode, int vertexCount,
+ const SkPoint vertices[], const SkPoint texs[],
+ const SkColor colors[], SkXfermode* xmode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawVertices(vmode, vertexCount, vertices, texs, colors,
+ xmode, indices, indexCount, paint);
+ }
+
+ virtual void drawData(const void* data, size_t length) OVERRIDE {
+ AutoStamper stamper(this);
+ SkProxyCanvas::drawData(data, length);
+ }
+
+private:
+ typedef base::hash_map<size_t, base::TimeDelta> TimingsMap;
+ TimingsMap timings_map_;
+
+ skia::RefPtr<SkCanvas> canvas_;
+
+ friend class AutoStamper;
+ const BenchmarkingCanvas* tracking_canvas_;
+};
+
+AutoStamper::AutoStamper(TimingCanvas *timing_canvas)
+ : timing_canvas_(timing_canvas) {
+ start_ticks_ = base::TimeTicks::HighResNow();
+}
+
+AutoStamper::~AutoStamper() {
+ base::TimeDelta delta = base::TimeTicks::HighResNow() - start_ticks_;
+ int command_index = timing_canvas_->tracking_canvas_->CommandCount();
+ timing_canvas_->timings_map_[command_index] = delta;
+}
+
+BenchmarkingCanvas::BenchmarkingCanvas(int width, int height)
+ : SkNWayCanvas(width, height) {
+ debug_canvas_ = skia::AdoptRef(SkNEW_ARGS(SkDebugCanvas, (width, height)));
+ timing_canvas_ = skia::AdoptRef(SkNEW_ARGS(TimingCanvas, (width, height, this)));
+
+ addCanvas(debug_canvas_.get());
+ addCanvas(timing_canvas_.get());
+}
+
+BenchmarkingCanvas::~BenchmarkingCanvas() {
+ removeAll();
+}
+
+size_t BenchmarkingCanvas::CommandCount() const {
+ return debug_canvas_->getSize();
+}
+
+SkDrawCommand* BenchmarkingCanvas::GetCommand(size_t index) {
+ DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
+ return debug_canvas_->getDrawCommandAt(index);
+}
+
+double BenchmarkingCanvas::GetTime(size_t index) {
+ DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
+ return timing_canvas_->GetTime(index);
+}
+
+} // namespace skia
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h
new file mode 100644
index 0000000..7ef8204
--- /dev/null
+++ b/skia/ext/benchmarking_canvas.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SKIA_EXT_BENCHMARKING_CANVAS_H_
+#define SKIA_EXT_BENCHMARKING_CANVAS_H_
+
+#include "base/compiler_specific.h"
+#include "skia/ext/refptr.h"
+#include "third_party/skia/include/utils/SkNWayCanvas.h"
+#include "third_party/skia/src/utils/debugger/SkDebugCanvas.h"
+
+namespace skia {
+
+class TimingCanvas;
+
+class SK_API BenchmarkingCanvas : public SkNWayCanvas {
+public:
+ BenchmarkingCanvas(int width, int height);
+ virtual ~BenchmarkingCanvas();
+
+ // Returns the number of draw commands executed on this canvas.
+ size_t CommandCount() const;
+
+ // Get draw command info for a given index.
+ SkDrawCommand* GetCommand(size_t index);
+
+ // Return the recorded render time (milliseconds) for a draw command index.
+ double GetTime(size_t index);
+
+private:
+ // In order to avoid introducing a Skia version dependency, this
+ // implementation dispatches draw commands in lock-step to two distinct
+ // canvases:
+ // * a SkDebugCanvas used for gathering command info and tracking
+ // the current command index
+ // * a SkiaTimingCanvas used for measuring raster paint times (and relying
+ // on the former for tracking the current command index).
+ //
+ // This way, if the SkCanvas API is extended, we don't need to worry about
+ // updating content::SkiaTimingCanvas to accurately override all new methods
+ // (to avoid timing info indices from getting out of sync), as SkDebugCanvas
+ // already does that for us.
+
+ skia::RefPtr<SkDebugCanvas> debug_canvas_;
+ skia::RefPtr<TimingCanvas> timing_canvas_;
+};
+
+}
+#endif // SKIA_EXT_BENCHMARKING_CANVAS_H
diff --git a/skia/skia_chrome.gypi b/skia/skia_chrome.gypi
index d47fc10..ecd9b47 100644
--- a/skia/skia_chrome.gypi
+++ b/skia/skia_chrome.gypi
@@ -27,6 +27,8 @@
'sources': [
'ext/analysis_canvas.cc',
'ext/analysis_canvas.h',
+ 'ext/benchmarking_canvas.cc',
+ 'ext/benchmarking_canvas.h',
'ext/bitmap_platform_device.h',
'ext/bitmap_platform_device_android.cc',
'ext/bitmap_platform_device_android.h',
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index 986efe4..299feb19 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -150,6 +150,7 @@
'../third_party/skia/include/utils/SkNWayCanvas.h',
'../third_party/skia/src/utils/SkNWayCanvas.cpp',
'../third_party/skia/src/utils/SkPictureUtils.cpp',
+ '../third_party/skia/src/utils/SkProxyCanvas.cpp',
'../third_party/skia/src/utils/SkRTConf.cpp',
'../third_party/skia/include/utils/SkRTConf.h',
'../third_party/skia/include/pdf/SkPDFDevice.h',
@@ -164,6 +165,7 @@
'../third_party/skia/include/utils/SkNullCanvas.h',
'../third_party/skia/include/utils/SkPictureUtils.h',
+ '../third_party/skia/include/utils/SkProxyCanvas.h',
],
'include_dirs': [
'..',