1 // Copyright (c) 2013 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.
4
5 #include "base/containers/hash_tables.h"
6 #include "base/logging.h"
7 #include "base/time/time.h"
8 #include "skia/ext/benchmarking_canvas.h"
9 #include "third_party/skia/include/utils/SkProxyCanvas.h"
10
11 namespace skia {
12
13 class AutoStamper {
14 public:
15 AutoStamper(TimingCanvas* timing_canvas);
16 ~AutoStamper();
17
18 private:
19 TimingCanvas* timing_canvas_;
20 base::TimeTicks start_ticks_;
21 };
22
23 class TimingCanvas : public SkProxyCanvas {
24 public:
TimingCanvas(int width,int height,const BenchmarkingCanvas * track_canvas)25 TimingCanvas(int width, int height, const BenchmarkingCanvas* track_canvas)
26 : tracking_canvas_(track_canvas) {
27 canvas_ = skia::AdoptRef(SkCanvas::NewRasterN32(width, height));
28
29 setProxy(canvas_.get());
30 }
31
~TimingCanvas()32 virtual ~TimingCanvas() {
33 }
34
GetTime(size_t index)35 double GetTime(size_t index) {
36 TimingsMap::const_iterator timing_info = timings_map_.find(index);
37 return timing_info != timings_map_.end()
38 ? timing_info->second.InMillisecondsF()
39 : 0.0;
40 }
41
42 // SkCanvas overrides.
willSave()43 virtual void willSave() OVERRIDE {
44 AutoStamper stamper(this);
45 SkProxyCanvas::willSave();
46 }
47
willSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)48 virtual SaveLayerStrategy willSaveLayer(const SkRect* bounds,
49 const SkPaint* paint,
50 SaveFlags flags) OVERRIDE {
51 AutoStamper stamper(this);
52 return SkProxyCanvas::willSaveLayer(bounds, paint, flags);
53 }
54
willRestore()55 virtual void willRestore() OVERRIDE {
56 AutoStamper stamper(this);
57 SkProxyCanvas::willRestore();
58 }
59
drawPaint(const SkPaint & paint)60 virtual void drawPaint(const SkPaint& paint) OVERRIDE {
61 AutoStamper stamper(this);
62 SkProxyCanvas::drawPaint(paint);
63 }
64
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)65 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
66 const SkPaint& paint) OVERRIDE {
67 AutoStamper stamper(this);
68 SkProxyCanvas::drawPoints(mode, count, pts, paint);
69 }
70
drawOval(const SkRect & rect,const SkPaint & paint)71 virtual void drawOval(const SkRect& rect, const SkPaint& paint) OVERRIDE {
72 AutoStamper stamper(this);
73 SkProxyCanvas::drawOval(rect, paint);
74 }
75
drawRect(const SkRect & rect,const SkPaint & paint)76 virtual void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE {
77 AutoStamper stamper(this);
78 SkProxyCanvas::drawRect(rect, paint);
79 }
80
drawRRect(const SkRRect & rrect,const SkPaint & paint)81 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) OVERRIDE {
82 AutoStamper stamper(this);
83 SkProxyCanvas::drawRRect(rrect, paint);
84 }
85
drawPath(const SkPath & path,const SkPaint & paint)86 virtual void drawPath(const SkPath& path, const SkPaint& paint) OVERRIDE {
87 AutoStamper stamper(this);
88 SkProxyCanvas::drawPath(path, paint);
89 }
90
drawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint=NULL)91 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
92 const SkPaint* paint = NULL) OVERRIDE {
93 AutoStamper stamper(this);
94 SkProxyCanvas::drawBitmap(bitmap, left, top, paint);
95 }
96
drawBitmapRectToRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)97 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
98 const SkRect& dst,
99 const SkPaint* paint,
100 DrawBitmapRectFlags flags) OVERRIDE {
101 AutoStamper stamper(this);
102 SkProxyCanvas::drawBitmapRectToRect(bitmap, src, dst, paint, flags);
103 }
104
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & m,const SkPaint * paint=NULL)105 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
106 const SkPaint* paint = NULL) OVERRIDE {
107 AutoStamper stamper(this);
108 SkProxyCanvas::drawBitmapMatrix(bitmap, m, paint);
109 }
110
drawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint=NULL)111 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
112 const SkPaint* paint = NULL) OVERRIDE {
113 AutoStamper stamper(this);
114 SkProxyCanvas::drawSprite(bitmap, left, top, paint);
115 }
116
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)117 virtual void drawVertices(VertexMode vmode, int vertexCount,
118 const SkPoint vertices[], const SkPoint texs[],
119 const SkColor colors[], SkXfermode* xmode,
120 const uint16_t indices[], int indexCount,
121 const SkPaint& paint) OVERRIDE {
122 AutoStamper stamper(this);
123 SkProxyCanvas::drawVertices(vmode, vertexCount, vertices, texs, colors,
124 xmode, indices, indexCount, paint);
125 }
126
drawData(const void * data,size_t length)127 virtual void drawData(const void* data, size_t length) OVERRIDE {
128 AutoStamper stamper(this);
129 SkProxyCanvas::drawData(data, length);
130 }
131
132 protected:
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)133 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
134 SkScalar y, const SkPaint& paint) OVERRIDE {
135 AutoStamper stamper(this);
136 SkProxyCanvas::onDrawText(text, byteLength, x, y, paint);
137 }
138
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)139 virtual void onDrawPosText(const void* text, size_t byteLength,
140 const SkPoint pos[],
141 const SkPaint& paint) OVERRIDE {
142 AutoStamper stamper(this);
143 SkProxyCanvas::onDrawPosText(text, byteLength, pos, paint);
144 }
145
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)146 virtual void onDrawPosTextH(const void* text, size_t byteLength,
147 const SkScalar xpos[], SkScalar constY,
148 const SkPaint& paint) OVERRIDE {
149 AutoStamper stamper(this);
150 SkProxyCanvas::onDrawPosTextH(text, byteLength, xpos, constY, paint);
151 }
152
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)153 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
154 const SkPath& path, const SkMatrix* matrix,
155 const SkPaint& paint) OVERRIDE {
156 AutoStamper stamper(this);
157 SkProxyCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint);
158 }
159
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle edge_style)160 virtual void onClipRect(const SkRect& rect, SkRegion::Op op,
161 ClipEdgeStyle edge_style) OVERRIDE {
162 AutoStamper stamper(this);
163 SkProxyCanvas::onClipRect(rect, op, edge_style);
164 }
165
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle edge_style)166 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op,
167 ClipEdgeStyle edge_style) OVERRIDE {
168 AutoStamper stamper(this);
169 SkProxyCanvas::onClipRRect(rrect, op, edge_style);
170 }
171
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle edge_style)172 virtual void onClipPath(const SkPath& path, SkRegion::Op op,
173 ClipEdgeStyle edge_style) OVERRIDE {
174 AutoStamper stamper(this);
175 SkProxyCanvas::onClipPath(path, op, edge_style);
176 }
177
onClipRegion(const SkRegion & region,SkRegion::Op op)178 virtual void onClipRegion(const SkRegion& region,
179 SkRegion::Op op) OVERRIDE {
180 AutoStamper stamper(this);
181 SkProxyCanvas::onClipRegion(region, op);
182 }
183
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)184 virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
185 const SkPaint* paint) OVERRIDE {
186 AutoStamper stamper(this);
187 SkProxyCanvas::onDrawPicture(picture, matrix, paint);
188 }
189
190 private:
191 typedef base::hash_map<size_t, base::TimeDelta> TimingsMap;
192 TimingsMap timings_map_;
193
194 skia::RefPtr<SkCanvas> canvas_;
195
196 friend class AutoStamper;
197 const BenchmarkingCanvas* tracking_canvas_;
198 };
199
AutoStamper(TimingCanvas * timing_canvas)200 AutoStamper::AutoStamper(TimingCanvas *timing_canvas)
201 : timing_canvas_(timing_canvas) {
202 start_ticks_ = base::TimeTicks::HighResNow();
203 }
204
~AutoStamper()205 AutoStamper::~AutoStamper() {
206 base::TimeDelta delta = base::TimeTicks::HighResNow() - start_ticks_;
207 int command_index = timing_canvas_->tracking_canvas_->CommandCount() - 1;
208 DCHECK_GE(command_index, 0);
209 timing_canvas_->timings_map_[command_index] = delta;
210 }
211
BenchmarkingCanvas(int width,int height)212 BenchmarkingCanvas::BenchmarkingCanvas(int width, int height)
213 : SkNWayCanvas(width, height) {
214 debug_canvas_ = skia::AdoptRef(SkNEW_ARGS(SkDebugCanvas, (width, height)));
215 timing_canvas_ = skia::AdoptRef(SkNEW_ARGS(TimingCanvas, (width, height, this)));
216
217 addCanvas(debug_canvas_.get());
218 addCanvas(timing_canvas_.get());
219 }
220
~BenchmarkingCanvas()221 BenchmarkingCanvas::~BenchmarkingCanvas() {
222 removeAll();
223 }
224
CommandCount() const225 size_t BenchmarkingCanvas::CommandCount() const {
226 return debug_canvas_->getSize();
227 }
228
GetCommand(size_t index)229 SkDrawCommand* BenchmarkingCanvas::GetCommand(size_t index) {
230 DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
231 return debug_canvas_->getDrawCommandAt(index);
232 }
233
GetTime(size_t index)234 double BenchmarkingCanvas::GetTime(size_t index) {
235 DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize()));
236 return timing_canvas_->GetTime(index);
237 }
238
239 } // namespace skia
240