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/core/SkBitmapDevice.h"
10 #include "third_party/skia/include/utils/SkProxyCanvas.h"
11
12 namespace skia {
13
14 class AutoStamper {
15 public:
16 AutoStamper(TimingCanvas* timing_canvas);
17 ~AutoStamper();
18
19 private:
20 TimingCanvas* timing_canvas_;
21 base::TimeTicks start_ticks_;
22 };
23
24 class TimingCanvas : public SkProxyCanvas {
25 public:
TimingCanvas(int width,int height,const BenchmarkingCanvas * track_canvas)26 TimingCanvas(int width, int height, const BenchmarkingCanvas* track_canvas)
27 : tracking_canvas_(track_canvas) {
28 skia::RefPtr<SkBaseDevice> device = skia::AdoptRef(
29 SkNEW_ARGS(SkBitmapDevice, (SkBitmap::kARGB_8888_Config, width, height)));
30 canvas_ = skia::AdoptRef(SkNEW_ARGS(SkCanvas, (device.get())));
31
32 setProxy(canvas_.get());
33 }
34
~TimingCanvas()35 virtual ~TimingCanvas() {
36 }
37
GetTime(size_t index)38 double GetTime(size_t index) {
39 TimingsMap::const_iterator timing_info = timings_map_.find(index);
40 return timing_info != timings_map_.end()
41 ? timing_info->second.InMillisecondsF()
42 : 0.0;
43 }
44
45 // SkCanvas overrides.
save(SaveFlags flags=kMatrixClip_SaveFlag)46 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) OVERRIDE {
47 AutoStamper stamper(this);
48 return SkProxyCanvas::save(flags);
49 }
50
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags=kARGB_ClipLayer_SaveFlag)51 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
52 SaveFlags flags = kARGB_ClipLayer_SaveFlag) OVERRIDE {
53 AutoStamper stamper(this);
54 return SkProxyCanvas::saveLayer(bounds, paint, flags);
55 }
56
restore()57 virtual void restore() OVERRIDE {
58 AutoStamper stamper(this);
59 SkProxyCanvas::restore();
60 }
61
clipRect(const SkRect & rect,SkRegion::Op op,bool doAa)62 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
63 bool doAa) OVERRIDE {
64 AutoStamper stamper(this);
65 return SkProxyCanvas::clipRect(rect, op, doAa);
66 }
67
clipRRect(const SkRRect & rrect,SkRegion::Op op,bool doAa)68 virtual bool clipRRect(const SkRRect& rrect, SkRegion::Op op,
69 bool doAa) OVERRIDE {
70 AutoStamper stamper(this);
71 return SkProxyCanvas::clipRRect(rrect, op, doAa);
72 }
73
clipPath(const SkPath & path,SkRegion::Op op,bool doAa)74 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
75 bool doAa) OVERRIDE {
76 AutoStamper stamper(this);
77 return SkProxyCanvas::clipPath(path, op, doAa);
78 }
79
clipRegion(const SkRegion & region,SkRegion::Op op=SkRegion::kIntersect_Op)80 virtual bool clipRegion(const SkRegion& region,
81 SkRegion::Op op = SkRegion::kIntersect_Op) OVERRIDE {
82 AutoStamper stamper(this);
83 return SkProxyCanvas::clipRegion(region, op);
84 }
85
drawPaint(const SkPaint & paint)86 virtual void drawPaint(const SkPaint& paint) OVERRIDE {
87 AutoStamper stamper(this);
88 SkProxyCanvas::drawPaint(paint);
89 }
90
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)91 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
92 const SkPaint& paint) OVERRIDE {
93 AutoStamper stamper(this);
94 SkProxyCanvas::drawPoints(mode, count, pts, paint);
95 }
96
drawOval(const SkRect & rect,const SkPaint & paint)97 virtual void drawOval(const SkRect& rect, const SkPaint& paint) OVERRIDE {
98 AutoStamper stamper(this);
99 SkProxyCanvas::drawOval(rect, paint);
100 }
101
drawRect(const SkRect & rect,const SkPaint & paint)102 virtual void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE {
103 AutoStamper stamper(this);
104 SkProxyCanvas::drawRect(rect, paint);
105 }
106
drawRRect(const SkRRect & rrect,const SkPaint & paint)107 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) OVERRIDE {
108 AutoStamper stamper(this);
109 SkProxyCanvas::drawRRect(rrect, paint);
110 }
111
drawPath(const SkPath & path,const SkPaint & paint)112 virtual void drawPath(const SkPath& path, const SkPaint& paint) OVERRIDE {
113 AutoStamper stamper(this);
114 SkProxyCanvas::drawPath(path, paint);
115 }
116
drawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint=NULL)117 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
118 const SkPaint* paint = NULL) OVERRIDE {
119 AutoStamper stamper(this);
120 SkProxyCanvas::drawBitmap(bitmap, left, top, paint);
121 }
122
drawBitmapRectToRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)123 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
124 const SkRect& dst,
125 const SkPaint* paint,
126 DrawBitmapRectFlags flags) OVERRIDE {
127 AutoStamper stamper(this);
128 SkProxyCanvas::drawBitmapRectToRect(bitmap, src, dst, paint, flags);
129 }
130
drawBitmapMatrix(const SkBitmap & bitmap,const SkMatrix & m,const SkPaint * paint=NULL)131 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
132 const SkPaint* paint = NULL) OVERRIDE {
133 AutoStamper stamper(this);
134 SkProxyCanvas::drawBitmapMatrix(bitmap, m, paint);
135 }
136
drawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint=NULL)137 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
138 const SkPaint* paint = NULL) OVERRIDE {
139 AutoStamper stamper(this);
140 SkProxyCanvas::drawSprite(bitmap, left, top, paint);
141 }
142
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)143 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
144 SkScalar y, const SkPaint& paint) OVERRIDE {
145 AutoStamper stamper(this);
146 SkProxyCanvas::drawText(text, byteLength, x, y, paint);
147 }
148
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)149 virtual void drawPosText(const void* text, size_t byteLength,
150 const SkPoint pos[],
151 const SkPaint& paint) OVERRIDE {
152 AutoStamper stamper(this);
153 SkProxyCanvas::drawPosText(text, byteLength, pos, paint);
154 }
155
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)156 virtual void drawPosTextH(const void* text, size_t byteLength,
157 const SkScalar xpos[], SkScalar constY,
158 const SkPaint& paint) OVERRIDE {
159 AutoStamper stamper(this);
160 SkProxyCanvas::drawPosTextH(text, byteLength, xpos, constY, paint);
161 }
162
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)163 virtual void drawTextOnPath(const void* text, size_t byteLength,
164 const SkPath& path, const SkMatrix* matrix,
165 const SkPaint& paint) OVERRIDE {
166 AutoStamper stamper(this);
167 SkProxyCanvas::drawTextOnPath(text, byteLength, path, matrix, paint);
168 }
169
drawPicture(SkPicture & picture)170 virtual void drawPicture(SkPicture& picture) OVERRIDE {
171 AutoStamper stamper(this);
172 SkProxyCanvas::drawPicture(picture);
173 }
174
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)175 virtual void drawVertices(VertexMode vmode, int vertexCount,
176 const SkPoint vertices[], const SkPoint texs[],
177 const SkColor colors[], SkXfermode* xmode,
178 const uint16_t indices[], int indexCount,
179 const SkPaint& paint) OVERRIDE {
180 AutoStamper stamper(this);
181 SkProxyCanvas::drawVertices(vmode, vertexCount, vertices, texs, colors,
182 xmode, indices, indexCount, paint);
183 }
184
drawData(const void * data,size_t length)185 virtual void drawData(const void* data, size_t length) OVERRIDE {
186 AutoStamper stamper(this);
187 SkProxyCanvas::drawData(data, length);
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