summaryrefslogtreecommitdiffstats
path: root/skia/ext
diff options
context:
space:
mode:
authorfmalita <fmalita@chromium.org>2015-02-26 07:48:42 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-26 15:49:27 +0000
commitf5190e0b6f8f56c5f715928b4c68d39564cb1988 (patch)
tree009ea8dec014c2c1e15cd7955d924567b32501c5 /skia/ext
parent721ec7f8578afb27b9664641b109d483439b9859 (diff)
downloadchromium_src-f5190e0b6f8f56c5f715928b4c68d39564cb1988.zip
chromium_src-f5190e0b6f8f56c5f715928b4c68d39564cb1988.tar.gz
chromium_src-f5190e0b6f8f56c5f715928b4c68d39564cb1988.tar.bz2
Refactor BenchmarkingCanvas to avoid internal Skia dependencies
Re-implement BenchmarkingCanvas functionality based on public Skia APIs only. Convert Skia types to base::Value() structured data hierarchies (which are then pass through to the viewer). BUG=457691 R=reed@google.com,robertphillips@google.com,nduca@chromium.org,pdr@chromium.org Review URL: https://codereview.chromium.org/942533002 Cr-Commit-Position: refs/heads/master@{#318236}
Diffstat (limited to 'skia/ext')
-rw-r--r--skia/ext/benchmarking_canvas.cc866
-rw-r--r--skia/ext/benchmarking_canvas.h87
2 files changed, 752 insertions, 201 deletions
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc
index 409d56b..0dd6949 100644
--- a/skia/ext/benchmarking_canvas.cc
+++ b/skia/ext/benchmarking_canvas.cc
@@ -2,250 +2,760 @@
// 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/strings/stringprintf.h"
#include "base/time/time.h"
#include "skia/ext/benchmarking_canvas.h"
-#include "third_party/skia/include/core/SkSurface.h"
-#include "third_party/skia/include/utils/SkNWayCanvas.h"
+#include "third_party/skia/include/core/SkColorFilter.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
+#include "third_party/skia/include/core/SkPicture.h"
+#include "third_party/skia/include/core/SkRegion.h"
+#include "third_party/skia/include/core/SkTextBlob.h"
+#include "third_party/skia/include/core/SkXfermode.h"
-namespace skia {
+namespace {
-class AutoStamper {
+class FlagsBuilder {
public:
- AutoStamper(TimingCanvas* timing_canvas);
- ~AutoStamper();
+ FlagsBuilder(char separator)
+ : separator_(separator) {}
+
+ void addFlag(bool flag_val, const char flag_name[]) {
+ if (!flag_val)
+ return;
+ if (!oss_.str().empty())
+ oss_ << separator_;
+
+ oss_ << flag_name;
+ }
+
+ std::string str() const {
+ return oss_.str();
+ }
private:
- TimingCanvas* timing_canvas_;
- base::TimeTicks start_ticks_;
+ char separator_;
+ std::ostringstream oss_;
};
-class TimingCanvas : public SkNWayCanvas {
-public:
- TimingCanvas(int width, int height, const BenchmarkingCanvas* track_canvas)
- : SkNWayCanvas(width, height)
- , tracking_canvas_(track_canvas) {
- surface_ = skia::AdoptRef(SkSurface::NewRasterN32Premul(width, height));
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(bool b) {
+ scoped_ptr<base::FundamentalValue> val(new base::FundamentalValue(b));
- addCanvas(surface_->getCanvas());
- }
+ return val.Pass();
+}
- ~TimingCanvas() override {}
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkScalar scalar) {
+ scoped_ptr<base::FundamentalValue> val(new base::FundamentalValue(scalar));
- 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;
- }
+ return val.Pass();
+}
- // SkCanvas overrides.
- void willSave() override {
- AutoStamper stamper(this);
- SkNWayCanvas::willSave();
- }
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkSize& size) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("width", AsValue(size.width()));
+ val->Set("height", AsValue(size.height()));
- SaveLayerStrategy willSaveLayer(const SkRect* bounds,
- const SkPaint* paint,
- SaveFlags flags) override {
- AutoStamper stamper(this);
- return SkNWayCanvas::willSaveLayer(bounds, paint, flags);
- }
+ return val.Pass();
+}
- void willRestore() override {
- AutoStamper stamper(this);
- SkNWayCanvas::willRestore();
- }
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPoint& point) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("x", AsValue(point.x()));
+ val->Set("y", AsValue(point.y()));
- void onDrawPaint(const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawPaint(paint);
- }
+ return val.Pass();
+}
- void onDrawPoints(PointMode mode,
- size_t count,
- const SkPoint pts[],
- const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawPoints(mode, count, pts, paint);
- }
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkRect& rect) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("left", AsValue(rect.fLeft));
+ val->Set("top", AsValue(rect.fTop));
+ val->Set("right", AsValue(rect.fRight));
+ val->Set("bottom", AsValue(rect.fBottom));
- void onDrawOval(const SkRect& rect, const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawOval(rect, paint);
- }
+ return val.Pass();
+}
- void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawRect(rect, paint);
- }
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkRRect& rrect) {
+ scoped_ptr<base::DictionaryValue> radii_val(new base::DictionaryValue());
+ radii_val->Set("upper-left", AsValue(rrect.radii(SkRRect::kUpperLeft_Corner)));
+ radii_val->Set("upper-right", AsValue(rrect.radii(SkRRect::kUpperRight_Corner)));
+ radii_val->Set("lower-right", AsValue(rrect.radii(SkRRect::kLowerRight_Corner)));
+ radii_val->Set("lower-left", AsValue(rrect.radii(SkRRect::kLowerLeft_Corner)));
- void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawRRect(rrect, paint);
- }
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("rect", AsValue(rrect.rect()));
+ val->Set("radii", radii_val.Pass());
- void onDrawPath(const SkPath& path, const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawPath(path, paint);
- }
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkMatrix& matrix) {
+ scoped_ptr<base::ListValue> val(new base::ListValue());
+ for (int i = 0; i < 9; ++i)
+ val->Append(AsValue(matrix[i]).release()); // no scoped_ptr-aware Append() variant
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkColor color) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->SetInteger("a", SkColorGetA(color));
+ val->SetInteger("r", SkColorGetR(color));
+ val->SetInteger("g", SkColorGetG(color));
+ val->SetInteger("b", SkColorGetB(color));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkXfermode::Mode mode) {
+ scoped_ptr<base::StringValue> val(
+ new base::StringValue(SkXfermode::ModeName(mode)));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkCanvas::PointMode mode) {
+ static const char* gModeStrings[] = { "Points", "Lines", "Polygon" };
+ DCHECK_LT(static_cast<size_t>(mode), SK_ARRAY_COUNT(gModeStrings));
- void onDrawBitmap(const SkBitmap& bitmap,
- SkScalar left,
- SkScalar top,
- const SkPaint* paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawBitmap(bitmap, left, top, paint);
+ scoped_ptr<base::StringValue> val(new base::StringValue(gModeStrings[mode]));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkXfermode& xfermode) {
+ SkXfermode::Mode mode;
+ if (xfermode.asMode(&mode))
+ return AsValue(mode);
+
+ scoped_ptr<base::StringValue> val(new base::StringValue("unknown"));
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkColorFilter& filter) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+
+ if (unsigned flags = filter.getFlags()) {
+ FlagsBuilder builder('|');
+ builder.addFlag(flags & SkColorFilter::kAlphaUnchanged_Flag,
+ "kAlphaUnchanged_Flag");
+ builder.addFlag(flags & SkColorFilter::kHasFilter16_Flag,
+ "kHasFilter16_Flag");
+
+ val->SetString("flags", builder.str());
}
- void onDrawBitmapRect(const SkBitmap& bitmap,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint* paint,
- DrawBitmapRectFlags flags) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawBitmapRect(bitmap, src, dst, paint, flags);
+ SkScalar color_matrix[20];
+ if (filter.asColorMatrix(color_matrix)) {
+ scoped_ptr<base::ListValue> color_matrix_val(new base::ListValue());
+ for (unsigned i = 0; i < 20; ++i)
+ color_matrix_val->Append(AsValue(color_matrix[i]).release());
+
+ val->Set("color_matrix", color_matrix_val.Pass());
}
- void onDrawSprite(const SkBitmap& bitmap,
- int left,
- int top,
- const SkPaint* paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawSprite(bitmap, left, top, paint);
+ SkColor color;
+ SkXfermode::Mode mode;
+ if (filter.asColorMode(&color, &mode)) {
+ scoped_ptr<base::DictionaryValue> color_mode_val(
+ new base::DictionaryValue());
+ color_mode_val->Set("color", AsValue(color));
+ color_mode_val->Set("mode", AsValue(mode));
+
+ val->Set("color_mode", color_mode_val.Pass());
}
- void onDrawVertices(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);
- SkNWayCanvas::onDrawVertices(vmode, vertexCount, vertices, texs, colors,
- xmode, indices, indexCount, paint);
+ if (filter.asComponentTable(nullptr)) {
+ scoped_ptr<base::DictionaryValue> component_table_val(
+ new base::DictionaryValue());
+ // use this as a marker for now
+ val->Set("component_table", component_table_val.Pass());
}
-protected:
- void onDrawText(const void* text,
- size_t byteLength,
- SkScalar x,
- SkScalar y,
- const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawText(text, byteLength, x, y, paint);
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkImageFilter& filter) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->SetInteger("inputs", filter.countInputs());
+
+ SkColorFilter* color_filter;
+ if (filter.asColorFilter(&color_filter)) {
+ val->Set("color_filter", AsValue(*color_filter));
+ SkSafeUnref(color_filter); // ref'd in asColorFilter
}
- void onDrawPosText(const void* text,
- size_t byteLength,
- const SkPoint pos[],
- const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawPosText(text, byteLength, pos, paint);
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPaint& paint) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ SkPaint default_paint;
+
+ if (paint.getColor() != default_paint.getColor())
+ val->Set("Color", AsValue(paint.getColor()));
+
+ if (paint.getStyle() != default_paint.getStyle()) {
+ static const char* gStyleStrings[] = { "Fill", "Stroke", "StrokeFill" };
+ DCHECK_LT(static_cast<size_t>(paint.getStyle()),
+ SK_ARRAY_COUNT(gStyleStrings));
+ val->SetString("Style", gStyleStrings[paint.getStyle()]);
}
- void onDrawPosTextH(const void* text,
- size_t byteLength,
- const SkScalar xpos[],
- SkScalar constY,
- const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawPosTextH(text, byteLength, xpos, constY, paint);
+ if (paint.getXfermode() != default_paint.getXfermode()) {
+ DCHECK(paint.getXfermode());
+ val->Set("Xfermode", AsValue(*paint.getXfermode()));
}
- void onDrawTextOnPath(const void* text,
- size_t byteLength,
- const SkPath& path,
- const SkMatrix* matrix,
- const SkPaint& paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint);
+ if (paint.getFlags()) {
+ FlagsBuilder builder('|');
+ builder.addFlag(paint.isAntiAlias(), "AntiAlias");
+ builder.addFlag(paint.isDither(), "Dither");
+ builder.addFlag(paint.isUnderlineText(), "UnderlineText");
+ builder.addFlag(paint.isStrikeThruText(), "StrikeThruText");
+ builder.addFlag(paint.isFakeBoldText(), "FakeBoldText");
+ builder.addFlag(paint.isLinearText(), "LinearText");
+ builder.addFlag(paint.isSubpixelText(), "SubpixelText");
+ builder.addFlag(paint.isDevKernText(), "DevKernText");
+ builder.addFlag(paint.isLCDRenderText(), "LCDRenderText");
+ builder.addFlag(paint.isEmbeddedBitmapText(), "EmbeddedBitmapText");
+ builder.addFlag(paint.isAutohinted(), "Autohinted");
+ builder.addFlag(paint.isVerticalText(), "VerticalText");
+ builder.addFlag(paint.getFlags() & SkPaint::kGenA8FromLCD_Flag,
+ "GenA8FromLCD");
+
+ val->SetString("Flags", builder.str());
}
- void onClipRect(const SkRect& rect,
- SkRegion::Op op,
- ClipEdgeStyle edge_style) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onClipRect(rect, op, edge_style);
+ if (paint.getFilterLevel() != default_paint.getFilterLevel()) {
+ static const char* gFilterLevelStrings[] =
+ { "None", "Low", "Medium", "High" };
+ DCHECK_LT(static_cast<size_t>(paint.getFilterLevel()),
+ SK_ARRAY_COUNT(gFilterLevelStrings));
+ val->SetString("FilterLevel", gFilterLevelStrings[paint.getFilterLevel()]);
}
- void onClipRRect(const SkRRect& rrect,
- SkRegion::Op op,
- ClipEdgeStyle edge_style) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onClipRRect(rrect, op, edge_style);
+ if (paint.getTextSize() != default_paint.getTextSize())
+ val->SetDouble("TextSize", paint.getTextSize());
+
+ if (paint.getTextScaleX() != default_paint.getTextScaleX())
+ val->SetDouble("TextScaleX", paint.getTextScaleX());
+
+ if (paint.getTextSkewX() != default_paint.getTextSkewX())
+ val->SetDouble("TextSkewX", paint.getTextSkewX());
+
+ if (paint.getColorFilter())
+ val->Set("ColorFilter", AsValue(*paint.getColorFilter()));
+
+ if (paint.getImageFilter())
+ val->Set("ImageFilter", AsValue(*paint.getImageFilter()));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkCanvas::SaveFlags flags) {
+ FlagsBuilder builder('|');
+ builder.addFlag(flags & SkCanvas::kHasAlphaLayer_SaveFlag,
+ "kHasAlphaLayer");
+ builder.addFlag(flags & SkCanvas::kFullColorLayer_SaveFlag,
+ "kFullColorLayer");
+ builder.addFlag(flags & SkCanvas::kClipToLayer_SaveFlag,
+ "kClipToLayer");
+
+ scoped_ptr<base::StringValue> val(new base::StringValue(builder.str()));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(SkRegion::Op op) {
+ static const char* gOpStrings[] = { "Difference",
+ "Intersect",
+ "Union",
+ "XOR",
+ "ReverseDifference",
+ "Replace"
+ };
+ DCHECK_LT(static_cast<size_t>(op), SK_ARRAY_COUNT(gOpStrings));
+ scoped_ptr<base::StringValue> val(new base::StringValue(gOpStrings[op]));
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkRegion& region) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("bounds", AsValue(SkRect::Make(region.getBounds())));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPicture& picture) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("cull-rect", AsValue(picture.cullRect()));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkBitmap& bitmap) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("size", AsValue(SkSize::Make(bitmap.width(), bitmap.height())));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkImage& image) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("size", AsValue(SkSize::Make(image.width(), image.height())));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkTextBlob& blob) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+ val->Set("bounds", AsValue(blob.bounds()));
+
+ return val.Pass();
+}
+
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsValue(const SkPath& path) {
+ scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
+
+ static const char* gFillStrings[] =
+ { "winding", "even-odd", "inverse-winding", "inverse-even-odd" };
+ DCHECK_LT(static_cast<size_t>(path.getFillType()),
+ SK_ARRAY_COUNT(gFillStrings));
+ val->SetString("fill-type", gFillStrings[path.getFillType()]);
+
+ static const char* gConvexityStrings[] = { "Unknown", "Convex", "Concave" };
+ DCHECK_LT(static_cast<size_t>(path.getConvexity()),
+ SK_ARRAY_COUNT(gConvexityStrings));
+ val->SetString("convexity", gConvexityStrings[path.getConvexity()]);
+
+ val->SetBoolean("is-rect", path.isRect(nullptr));
+ val->Set("bounds", AsValue(path.getBounds()));
+
+ static const char* gVerbStrings[] =
+ { "move", "line", "quad", "conic", "cubic", "close", "done" };
+ static const int gPtsPerVerb[] = { 1, 1, 2, 2, 3, 0, 0 };
+ static const int gPtOffsetPerVerb[] = { 0, 1, 1, 1, 1, 0, 0 };
+ SK_COMPILE_ASSERT(
+ SK_ARRAY_COUNT(gVerbStrings) == static_cast<size_t>(SkPath::kDone_Verb + 1),
+ gVerbStrings_size_mismatch);
+ SK_COMPILE_ASSERT(
+ SK_ARRAY_COUNT(gVerbStrings) == SK_ARRAY_COUNT(gPtsPerVerb),
+ gPtsPerVerb_size_mismatch);
+ SK_COMPILE_ASSERT(
+ SK_ARRAY_COUNT(gVerbStrings) == SK_ARRAY_COUNT(gPtOffsetPerVerb),
+ gPtOffsetPerVerb_size_mismatch);
+
+ scoped_ptr<base::ListValue> verbs_val(new base::ListValue());
+ SkPath::Iter iter(const_cast<SkPath&>(path), false);
+ SkPoint points[4];
+
+ for(SkPath::Verb verb = iter.next(points, false);
+ verb != SkPath::kDone_Verb; verb = iter.next(points, false)) {
+ DCHECK_LT(static_cast<size_t>(verb), SK_ARRAY_COUNT(gVerbStrings));
+
+ scoped_ptr<base::DictionaryValue> verb_val(new base::DictionaryValue());
+ scoped_ptr<base::ListValue> pts_val(new base::ListValue());
+
+ for (int i = 0; i < gPtsPerVerb[verb]; ++i)
+ pts_val->Append(AsValue(points[i + gPtOffsetPerVerb[verb]]).release());
+
+ verb_val->Set(gVerbStrings[verb], pts_val.Pass());
+
+ if (SkPath::kConic_Verb == verb)
+ verb_val->Set("weight", AsValue(iter.conicWeight()));
+
+ verbs_val->Append(verb_val.release());
}
+ val->Set("verbs", verbs_val.Pass());
+
+ return val.Pass();
+}
+
+template<typename T>
+WARN_UNUSED_RESULT
+scoped_ptr<base::Value> AsListValue(const T array[], size_t count) {
+ scoped_ptr<base::ListValue> val(new base::ListValue());
+
+ for (size_t i = 0; i < count; ++i)
+ val->Append(AsValue(array[i]).release());
+
+ return val.Pass();
+}
+
+} // namespace
+
+namespace skia {
+
+class BenchmarkingCanvas::AutoOp {
+public:
+ AutoOp(BenchmarkingCanvas* canvas, const char op_name[],
+ const SkPaint* paint = nullptr)
+ : canvas_(canvas)
+ , op_record_(new base::DictionaryValue())
+ , op_params_(new base::ListValue()) {
+
+ DCHECK(canvas);
+ DCHECK(op_name);
- void onClipPath(const SkPath& path,
- SkRegion::Op op,
- ClipEdgeStyle edge_style) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onClipPath(path, op, edge_style);
+ op_record_->SetString("cmd_string", op_name);
+ op_record_->Set("info", op_params_);
+
+ if (paint)
+ this->addParam("paint", AsValue(*paint));
+
+ start_ticks_ = base::TimeTicks::Now();
}
- void onClipRegion(const SkRegion& region, SkRegion::Op op) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onClipRegion(region, op);
+ ~AutoOp() {
+ base::TimeDelta ticks = base::TimeTicks::Now() - start_ticks_;
+ op_record_->SetDouble("cmd_time", ticks.InMillisecondsF());
+
+ canvas_->op_records_.Append(op_record_);
}
- void onDrawPicture(const SkPicture* picture,
- const SkMatrix* matrix,
- const SkPaint* paint) override {
- AutoStamper stamper(this);
- SkNWayCanvas::onDrawPicture(picture, matrix, paint);
+ void addParam(const char name[], scoped_ptr<base::Value> value) {
+ scoped_ptr<base::DictionaryValue> param(new base::DictionaryValue());
+ param->Set(name, value.Pass());
+
+ op_params_->Append(param.release());
}
private:
- typedef base::hash_map<size_t, base::TimeDelta> TimingsMap;
- TimingsMap timings_map_;
+ BenchmarkingCanvas* canvas_;
+ base::DictionaryValue* op_record_;
+ base::ListValue* op_params_;
+ base::TimeTicks start_ticks_;
+};
- skia::RefPtr<SkSurface> surface_;
+BenchmarkingCanvas::BenchmarkingCanvas(SkCanvas* canvas, unsigned flags)
+ : INHERITED(canvas->imageInfo().width(),
+ canvas->imageInfo().height())
+ , flags_(flags) {
+ addCanvas(canvas);
+}
- friend class AutoStamper;
- const BenchmarkingCanvas* tracking_canvas_;
-};
+BenchmarkingCanvas::~BenchmarkingCanvas() {
+}
-AutoStamper::AutoStamper(TimingCanvas *timing_canvas)
- : timing_canvas_(timing_canvas) {
- start_ticks_ = base::TimeTicks::Now();
+size_t BenchmarkingCanvas::CommandCount() const {
+ return op_records_.GetSize();
}
-AutoStamper::~AutoStamper() {
- base::TimeDelta delta = base::TimeTicks::Now() - start_ticks_;
- int command_index = timing_canvas_->tracking_canvas_->CommandCount() - 1;
- DCHECK_GE(command_index, 0);
- timing_canvas_->timings_map_[command_index] = delta;
+const base::ListValue& BenchmarkingCanvas::Commands() const {
+ return op_records_;
}
-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)));
+double BenchmarkingCanvas::GetTime(size_t index) {
+ const base::DictionaryValue* op;
+ if (!op_records_.GetDictionary(index, &op))
+ return 0;
- addCanvas(debug_canvas_.get());
- addCanvas(timing_canvas_.get());
+ double t;
+ if (!op->GetDouble("cmd_time", &t))
+ return 0;
+
+ return t;
}
-BenchmarkingCanvas::~BenchmarkingCanvas() {
- removeAll();
+void BenchmarkingCanvas::willSave() {
+ AutoOp op(this, "Save");
+
+ INHERITED::willSave();
}
-size_t BenchmarkingCanvas::CommandCount() const {
- return debug_canvas_->getSize();
+SkCanvas::SaveLayerStrategy BenchmarkingCanvas::willSaveLayer(const SkRect* rect,
+ const SkPaint* paint,
+ SaveFlags flags) {
+ AutoOp op(this, "SaveLayer", paint);
+ if (rect)
+ op.addParam("bounds", AsValue(*rect));
+ if (paint)
+ op.addParam("paint", AsValue(*paint));
+ if (flags)
+ op.addParam("flags", AsValue(flags));
+
+ return INHERITED::willSaveLayer(rect, paint, flags);
}
-SkDrawCommand* BenchmarkingCanvas::GetCommand(size_t index) {
- DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
- return debug_canvas_->getDrawCommandAt(index);
+void BenchmarkingCanvas::willRestore() {
+ AutoOp op(this, "Restore");
+
+ INHERITED::willRestore();
}
-double BenchmarkingCanvas::GetTime(size_t index) {
- DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
- return timing_canvas_->GetTime(index);
+void BenchmarkingCanvas::didConcat(const SkMatrix& m) {
+ AutoOp op(this, "Concat");
+ op.addParam("matrix", AsValue(m));
+
+ INHERITED::didConcat(m);
+}
+
+void BenchmarkingCanvas::didSetMatrix(const SkMatrix& m) {
+ AutoOp op(this, "SetMatrix");
+ op.addParam("matrix", AsValue(m));
+
+ INHERITED::didSetMatrix(m);
+}
+
+void BenchmarkingCanvas::onClipRect(const SkRect& rect,
+ SkRegion::Op region_op,
+ SkCanvas::ClipEdgeStyle style) {
+ AutoOp op(this, "ClipRect");
+ op.addParam("rect", AsValue(rect));
+ op.addParam("op", AsValue(region_op));
+ op.addParam("anti-alias", AsValue(style == kSoft_ClipEdgeStyle));
+
+ INHERITED::onClipRect(rect, region_op, style);
+}
+
+void BenchmarkingCanvas::onClipRRect(const SkRRect& rrect,
+ SkRegion::Op region_op,
+ SkCanvas::ClipEdgeStyle style) {
+ AutoOp op(this, "ClipRRect");
+ op.addParam("rrect", AsValue(rrect));
+ op.addParam("op", AsValue(region_op));
+ op.addParam("anti-alias", AsValue(style == kSoft_ClipEdgeStyle));
+
+ INHERITED::onClipRRect(rrect, region_op, style);
+}
+
+void BenchmarkingCanvas::onClipPath(const SkPath& path,
+ SkRegion::Op region_op,
+ SkCanvas::ClipEdgeStyle style) {
+ AutoOp op(this, "ClipPath");
+ op.addParam("path", AsValue(path));
+ op.addParam("op", AsValue(region_op));
+ op.addParam("anti-alias", AsValue(style == kSoft_ClipEdgeStyle));
+
+ INHERITED::onClipPath(path, region_op, style);
+}
+
+void BenchmarkingCanvas::onClipRegion(const SkRegion& region,
+ SkRegion::Op region_op) {
+ AutoOp op(this, "ClipRegion");
+ op.addParam("region", AsValue(region));
+ op.addParam("op", AsValue(region_op));
+
+ INHERITED::onClipRegion(region, region_op);
+}
+
+void BenchmarkingCanvas::onDrawPaint(const SkPaint& paint) {
+ AutoOp op(this, "DrawPaint", &paint);
+
+ INHERITED::onDrawPaint(paint);
+}
+
+void BenchmarkingCanvas::onDrawPoints(PointMode mode, size_t count,
+ const SkPoint pts[], const SkPaint& paint) {
+ AutoOp op(this, "DrawPoints", &paint);
+ op.addParam("mode", AsValue(mode));
+ op.addParam("points", AsListValue(pts, count));
+
+ INHERITED::onDrawPoints(mode, count, pts, paint);
+}
+
+void BenchmarkingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
+ AutoOp op(this, "DrawRect", &paint);
+ op.addParam("rect", AsValue(rect));
+
+ INHERITED::onDrawRect(rect, paint);
+}
+
+void BenchmarkingCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
+ AutoOp op(this, "DrawOval", &paint);
+ op.addParam("rect", AsValue(rect));
+
+ INHERITED::onDrawOval(rect, paint);
+}
+
+void BenchmarkingCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
+ AutoOp op(this, "DrawRRect", &paint);
+ op.addParam("rrect", AsValue(rrect));
+
+ INHERITED::onDrawRRect(rrect, paint);
+}
+
+void BenchmarkingCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+ const SkPaint& paint) {
+ AutoOp op(this, "DrawDRRect", &paint);
+ op.addParam("outer", AsValue(outer));
+ op.addParam("inner", AsValue(inner));
+
+ INHERITED::onDrawDRRect(outer, inner, paint);
+}
+
+void BenchmarkingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
+ AutoOp op(this, "DrawPath", &paint);
+ op.addParam("path", AsValue(path));
+
+ INHERITED::onDrawPath(path, paint);
+}
+
+void BenchmarkingCanvas::onDrawPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) {
+ DCHECK(picture);
+ AutoOp op(this, "DrawPicture", paint);
+ op.addParam("picture", AsValue(picture));
+ if (matrix)
+ op.addParam("matrix", AsValue(*matrix));
+
+ INHERITED::drawPicture(picture, matrix, paint);
+}
+
+void BenchmarkingCanvas::onDrawBitmap(const SkBitmap& bitmap,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint) {
+ AutoOp op(this, "DrawBitmap", paint);
+ op.addParam("bitmap", AsValue(bitmap));
+ op.addParam("left", AsValue(left));
+ op.addParam("top", AsValue(top));
+
+ INHERITED::onDrawBitmap(bitmap, left, top, paint);
+}
+
+void BenchmarkingCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
+ const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint,
+ DrawBitmapRectFlags flags) {
+ AutoOp op(this, "DrawBitmapRect", paint);
+ op.addParam("bitmap", AsValue(bitmap));
+ if (src)
+ op.addParam("src", AsValue(*src));
+ op.addParam("dst", AsValue(dst));
+
+ INHERITED::onDrawBitmapRect(bitmap, src, dst, paint, flags);
+}
+
+void BenchmarkingCanvas::onDrawImage(const SkImage* image,
+ SkScalar left,
+ SkScalar top,
+ const SkPaint* paint) {
+ DCHECK(image);
+ AutoOp op(this, "DrawImage", paint);
+ op.addParam("image", AsValue(*image));
+ op.addParam("left", AsValue(left));
+ op.addParam("top", AsValue(top));
+
+ INHERITED::onDrawImage(image, left, top, paint);
+}
+
+void BenchmarkingCanvas::onDrawImageRect(const SkImage* image, const SkRect* src,
+ const SkRect& dst, const SkPaint* paint) {
+ DCHECK(image);
+ AutoOp op(this, "DrawImageRect", paint);
+ op.addParam("image", AsValue(*image));
+ if (src)
+ op.addParam("src", AsValue(*src));
+ op.addParam("dst", AsValue(dst));
+
+ INHERITED::onDrawImageRect(image, src, dst, paint);
+}
+
+void BenchmarkingCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
+ const SkIRect& center,
+ const SkRect& dst,
+ const SkPaint* paint) {
+ AutoOp op(this, "DrawBitmapNine", paint);
+ op.addParam("bitmap", AsValue(bitmap));
+ op.addParam("center", AsValue(SkRect::Make(center)));
+ op.addParam("dst", AsValue(dst));
+
+ INHERITED::onDrawBitmapNine(bitmap, center, dst, paint);
+}
+
+void BenchmarkingCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top,
+ const SkPaint* paint) {
+ AutoOp op(this, "DrawSprite", paint);
+ op.addParam("bitmap", AsValue(bitmap));
+ op.addParam("left", AsValue(SkIntToScalar(left)));
+ op.addParam("top", AsValue(SkIntToScalar(top)));
+
+ INHERITED::onDrawSprite(bitmap, left, top, paint);
+}
+
+void BenchmarkingCanvas::onDrawText(const void* text, size_t byteLength,
+ SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ AutoOp op(this, "DrawText", &paint);
+ op.addParam("count", AsValue(SkIntToScalar(paint.countText(text, byteLength))));
+ op.addParam("x", AsValue(x));
+ op.addParam("y", AsValue(y));
+
+ INHERITED::onDrawText(text, byteLength, x, y, paint);
+}
+
+void BenchmarkingCanvas::onDrawPosText(const void* text, size_t byteLength,
+ const SkPoint pos[], const SkPaint& paint) {
+ AutoOp op(this, "DrawPosText", &paint);
+
+ int count = paint.countText(text, byteLength);
+ op.addParam("count", AsValue(SkIntToScalar(count)));
+ op.addParam("pos", AsListValue(pos, count));
+
+ INHERITED::onDrawPosText(text, byteLength, pos, paint);
+}
+
+void BenchmarkingCanvas::onDrawPosTextH(const void* text, size_t byteLength,
+ const SkScalar xpos[], SkScalar constY,
+ const SkPaint& paint) {
+ AutoOp op(this, "DrawPosTextH", &paint);
+ op.addParam("constY", AsValue(constY));
+
+ int count = paint.countText(text, byteLength);
+ op.addParam("count", AsValue(SkIntToScalar(count)));
+ op.addParam("pos", AsListValue(xpos, count));
+
+ INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, paint);
+}
+
+void BenchmarkingCanvas::onDrawTextOnPath(const void* text, size_t byteLength,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ AutoOp op(this, "DrawTextOnPath", &paint);
+ op.addParam("count", AsValue(SkIntToScalar(paint.countText(text, byteLength))));
+ op.addParam("path", AsValue(path));
+ if (matrix)
+ op.addParam("matrix", AsValue(*matrix));
+
+ INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint);
+}
+
+void BenchmarkingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ DCHECK(blob);
+ AutoOp op(this, "DrawTextBlob", &paint);
+ op.addParam("blob", AsValue(*blob));
+ op.addParam("x", AsValue(x));
+ op.addParam("y", AsValue(y));
+
+ INHERITED::onDrawTextBlob(blob, x, y, paint);
}
} // namespace skia
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h
index 50289a5..4f2e257 100644
--- a/skia/ext/benchmarking_canvas.h
+++ b/skia/ext/benchmarking_canvas.h
@@ -5,45 +5,86 @@
#ifndef SKIA_EXT_BENCHMARKING_CANVAS_H_
#define SKIA_EXT_BENCHMARKING_CANVAS_H_
-#include "base/compiler_specific.h"
-#include "skia/ext/refptr.h"
+#include "base/values.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);
+ BenchmarkingCanvas(SkCanvas* canvas, unsigned flags = 0);
~BenchmarkingCanvas() override;
+ enum Flags {
+ // TODO(fmalita): add overdraw visualization support
+ // (http://crbug.com/461534)
+ kOverdrawVisualization_Flag = 0x01,
+ };
+
// 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);
+ // Returns the list of executed draw commands.
+ const base::ListValue& Commands() const;
// Return the recorded render time (milliseconds) for a draw command index.
double GetTime(size_t index);
+protected:
+ // SkCanvas overrides
+ void willSave() override;
+ SaveLayerStrategy willSaveLayer(const SkRect*,
+ const SkPaint*,
+ SaveFlags) override;
+ void willRestore() override;
+
+ void didConcat(const SkMatrix&) override;
+ void didSetMatrix(const SkMatrix&) override;
+
+ void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
+ void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
+ void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
+ void onClipRegion(const SkRegion&, SkRegion::Op) override;
+
+ void onDrawPaint(const SkPaint&) override;
+ void onDrawPoints(PointMode, size_t count, const SkPoint pts[],
+ const SkPaint&) override;
+ void onDrawRect(const SkRect&, const SkPaint&) override;
+ void onDrawOval(const SkRect&, const SkPaint&) override;
+ void onDrawRRect(const SkRRect&, const SkPaint&) override;
+ void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
+ void onDrawPath(const SkPath&, const SkPaint&) override;
+
+ void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+ void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
+ void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst,
+ const SkPaint*, DrawBitmapRectFlags flags) override;
+ void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
+ void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
+ const SkPaint*) override;
+ void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
+ const SkPaint*) override;
+ void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;
+
+ void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+ const SkPaint&) override;
+ void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+ const SkPaint&) override;
+ void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+ SkScalar constY, const SkPaint&) override;
+ void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
+ const SkMatrix* matrix, const SkPaint&) override;
+ void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint) override;
+
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_;
+ typedef SkNWayCanvas INHERITED;
+
+ class AutoOp;
+
+ base::ListValue op_records_;
+ unsigned flags_;
};
}