Chromium Code Reviews| Index: skia/ext/analysis_canvas.cc |
| diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4fa2d95fdc4d1a9e48b710d47145789e9ff3e457 |
| --- /dev/null |
| +++ b/skia/ext/analysis_canvas.cc |
| @@ -0,0 +1,188 @@ |
| +// 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/debug/trace_event.h" |
| +#include "skia/ext/analysis_canvas.h" |
| + |
| +namespace skia { |
| + |
| +AnalysisDevice::AnalysisDevice(const SkBitmap& bm) : SkDevice(bm) { } |
| + |
| +AnalysisCanvas::AnalysisCanvas(SkDevice* device, SkRect clip) |
| + : SkCanvas(device) |
| + , estimatedCost_(0) |
| + , clip_(clip) { |
| + SkIRect ir; |
| + clip.roundOut(&ir); |
| + this->setClipRegion(SkRegion(ir)); |
| +} |
| + |
| +AnalysisCanvas::~AnalysisCanvas() { |
| + |
| +} |
| + |
| + |
| +int AnalysisCanvas::save(SkCanvas::SaveFlags) { |
|
Justin Novosad
2013/02/04 22:03:31
Some forward thinking here... In a future iteratio
|
| + ++estimatedCost_; |
| +} |
| + |
| +int AnalysisCanvas::saveLayer(const SkRect*, const SkPaint*, |
| + SkCanvas::SaveFlags) { |
| + ++estimatedCost_; |
|
Justin Novosad
2013/02/04 22:03:31
In the case of save layer we want to flow-through
Tom Hudson
2013/02/05 17:02:00
Done.
I'm not sure about the clipRectBounds, thou
|
| +} |
| + |
| +void AnalysisCanvas::restore() { |
| + ++estimatedCost_; |
|
Justin Novosad
2013/02/04 22:03:31
flow-though
|
| +} |
| + |
| +bool AnalysisCanvas::clipRect(const SkRect&, SkRegion::Op, bool) { |
| + ++estimatedCost_; |
|
Justin Novosad
2013/02/04 22:03:31
You want this to flow-through to base class, force
Tom Hudson
2013/02/05 17:02:00
Done.
I'm not sure about forcing AA to false, tho
|
| +} |
| + |
| +bool AnalysisCanvas::clipRRect(const SkRRect&, SkRegion::Op, bool) { |
| + ++estimatedCost_; |
|
Justin Novosad
2013/02/04 22:03:31
We need this to flow-through to base class, but we
|
| +} |
| + |
| +bool AnalysisCanvas::clipPath(const SkPath&, SkRegion::Op, bool) { |
| + ++estimatedCost_; |
|
Justin Novosad
2013/02/04 22:03:31
Same here, redirect to clipRect with path.bounds,
|
| +} |
| + |
| +bool AnalysisCanvas::clipRegion(const SkRegion&, SkRegion::Op) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::clear(SkColor) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawPaint(const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawPoints(PointMode, size_t, const SkPoint [], |
| + const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawRect(const SkRect&, const SkPaint&) { |
| +// FIXME: if there's a pending image decode & resize, more expensive |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawOval(const SkRect&, const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawRRect(const SkRRect&, const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawPath(const SkPath& path, const SkPaint& paint) { |
| +char tmpbuf [256]; |
| +sprintf(tmpbuf, "AnalysisCanvas::drawPath effect %s fill %s", paint.getPathEffect() ? "true" : "false", paint.getStyle() == SkPaint::kFill_Style ? "true" : "false"); |
| +TRACE_EVENT0("skia", strdup(tmpbuf)); |
| + // if the path is filled, and there's a mask filter, more expensive |
| + // FIXME: this isn't correctly detecting yet; no paths are taking |
| + // the branch. See SkDraw::drawPath() for the code we're attempting |
| + // to reproduce. Although none of the drawPath calls have a mask filter |
| + // attached at analysis time, on entry to SkDraw::drawPath the expensive |
| + // ones do! |
| + bool doFill = true; |
| + if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { |
| +TRACE_EVENT0("skia", "Checking fill path..."); |
| + SkPath tmpPath; |
| + doFill = paint.getFillPath(path, &tmpPath, &clip_); |
| + } |
| + if (doFill && paint.getMaskFilter()) { |
|
Justin Novosad
2013/02/04 22:03:31
The Mask filter should result in the same perf pen
Tom Hudson
2013/02/05 10:23:24
You're correct, but right now I have evidence of s
Tom Hudson
2013/02/05 17:02:00
Done.
|
| +TRACE_EVENT0("skia", "Found filled masked path; ouch!"); |
| + estimatedCost_ += 100; |
|
Justin Novosad
2013/02/04 22:03:31
Cost of mask filter does not depend on fill vs. st
|
| + } |
| + if (!paint.getMaskFilter()) { |
| +TRACE_EVENT0("skia", "No mask filter."); |
| + } |
| + ++estimatedCost_; |
| + |
| +} |
| + |
| +void AnalysisCanvas::drawBitmap(const SkBitmap&, SkScalar, SkScalar, |
| + const SkPaint&) { |
| + ++estimatedCost_; |
|
Justin Novosad
2013/02/04 22:03:31
If you gathered stats in an SkDevice-derived class
Tom Hudson
2013/02/05 17:02:00
Done.
|
| +} |
| + |
| +void AnalysisCanvas::drawBitmapRectToRect(const SkBitmap&, const SkRect*, |
| + const SkRect&, const SkPaint*) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&, |
| + const SkPaint*) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawBitmapNine(const SkBitmap&, const SkIRect&, |
| + const SkRect&, const SkPaint*) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawSprite(const SkBitmap&, int left, int top, |
| + const SkPaint*) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawText(const void*, size_t, SkScalar, SkScalar, |
|
Justin Novosad
2013/02/04 22:03:31
If you gathered stats in an SkDevice-derived class
Tom Hudson
2013/02/05 17:02:00
Done.
|
| + const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawPosText(const void*, size_t, const SkPoint [], |
| + const SkPaint&) { |
| +// FIXME: sometimes very expensive |
| +// NOT proportional to length: we see ~40B inputs taking 10-500 us |
| +// The difference seems to be cache misses; every miss adds 10-30 us, |
| +// and we might see 8 misses in 52B and spend >200us drawing a string |
| +// immediately after drawing a 48B string in 2us (!) with no misses. |
| +// https://code.google.com/p/skia/issues/detail?id=1102 |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawPosTextH(const void*, size_t, const SkScalar [], |
| + SkScalar, const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawTextOnPath(const void*, size_t, const SkPath&, |
| + const SkMatrix*, const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawVertices(VertexMode, int, const SkPoint [], |
| + const SkPoint [], const SkColor [], |
| + SkXfermode*, |
| + const uint16_t [], int, const SkPaint&) { |
| + ++estimatedCost_; |
| +} |
| + |
| +void AnalysisCanvas::drawData(const void*, size_t) { |
| + ++estimatedCost_; |
| +} |
| + |
| + |
| +int AnalysisCanvas::getEstimatedCost() const { |
| + return estimatedCost_; |
| +} |
| + |
| + |
| +void AnalysisCanvas::reset(SkRect clip) { |
| + estimatedCost_ = 0; |
| + clip_ = clip; |
| + SkIRect ir; |
| + clip.roundOut(&ir); |
| + this->setClipRegion(SkRegion(ir)); |
| +} |
| + |
| + |
| + |
| +} // namespace skia |
| + |
| + |