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: 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 32 virtual ~TimingCanvas() { 33 } 34 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. 43 virtual void willSave() OVERRIDE { 44 AutoStamper stamper(this); 45 SkProxyCanvas::willSave(); 46 } 47 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 55 virtual void willRestore() OVERRIDE { 56 AutoStamper stamper(this); 57 SkProxyCanvas::willRestore(); 58 } 59 60 virtual void drawPaint(const SkPaint& paint) OVERRIDE { 61 AutoStamper stamper(this); 62 SkProxyCanvas::drawPaint(paint); 63 } 64 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 71 virtual void drawOval(const SkRect& rect, const SkPaint& paint) OVERRIDE { 72 AutoStamper stamper(this); 73 SkProxyCanvas::drawOval(rect, paint); 74 } 75 76 virtual void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE { 77 AutoStamper stamper(this); 78 SkProxyCanvas::drawRect(rect, paint); 79 } 80 81 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) OVERRIDE { 82 AutoStamper stamper(this); 83 SkProxyCanvas::drawRRect(rrect, paint); 84 } 85 86 virtual void drawPath(const SkPath& path, const SkPaint& paint) OVERRIDE { 87 AutoStamper stamper(this); 88 SkProxyCanvas::drawPath(path, paint); 89 } 90 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 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 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 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 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 127 virtual void drawData(const void* data, size_t length) OVERRIDE { 128 AutoStamper stamper(this); 129 SkProxyCanvas::drawData(data, length); 130 } 131 132 protected: 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 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 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 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 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 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 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 178 virtual void onClipRegion(const SkRegion& region, 179 SkRegion::Op op) OVERRIDE { 180 AutoStamper stamper(this); 181 SkProxyCanvas::onClipRegion(region, op); 182 } 183 184 virtual void onDrawPicture(const SkPicture* picture) OVERRIDE { 185 AutoStamper stamper(this); 186 SkProxyCanvas::onDrawPicture(picture); 187 } 188 189 private: 190 typedef base::hash_map<size_t, base::TimeDelta> TimingsMap; 191 TimingsMap timings_map_; 192 193 skia::RefPtr<SkCanvas> canvas_; 194 195 friend class AutoStamper; 196 const BenchmarkingCanvas* tracking_canvas_; 197 }; 198 199 AutoStamper::AutoStamper(TimingCanvas *timing_canvas) 200 : timing_canvas_(timing_canvas) { 201 start_ticks_ = base::TimeTicks::HighResNow(); 202 } 203 204 AutoStamper::~AutoStamper() { 205 base::TimeDelta delta = base::TimeTicks::HighResNow() - start_ticks_; 206 int command_index = timing_canvas_->tracking_canvas_->CommandCount() - 1; 207 DCHECK_GE(command_index, 0); 208 timing_canvas_->timings_map_[command_index] = delta; 209 } 210 211 BenchmarkingCanvas::BenchmarkingCanvas(int width, int height) 212 : SkNWayCanvas(width, height) { 213 debug_canvas_ = skia::AdoptRef(SkNEW_ARGS(SkDebugCanvas, (width, height))); 214 timing_canvas_ = skia::AdoptRef(SkNEW_ARGS(TimingCanvas, (width, height, this))); 215 216 addCanvas(debug_canvas_.get()); 217 addCanvas(timing_canvas_.get()); 218 } 219 220 BenchmarkingCanvas::~BenchmarkingCanvas() { 221 removeAll(); 222 } 223 224 size_t BenchmarkingCanvas::CommandCount() const { 225 return debug_canvas_->getSize(); 226 } 227 228 SkDrawCommand* BenchmarkingCanvas::GetCommand(size_t index) { 229 DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize())); 230 return debug_canvas_->getDrawCommandAt(index); 231 } 232 233 double BenchmarkingCanvas::GetTime(size_t index) { 234 DCHECK_LT(index, static_cast<size_t>(debug_canvas_->getSize())); 235 return timing_canvas_->GetTime(index); 236 } 237 238 } // namespace skia 239