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: 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 35 virtual ~TimingCanvas() { 36 } 37 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. 46 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag) OVERRIDE { 47 AutoStamper stamper(this); 48 return SkProxyCanvas::save(flags); 49 } 50 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 57 virtual void restore() OVERRIDE { 58 AutoStamper stamper(this); 59 SkProxyCanvas::restore(); 60 } 61 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 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 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 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 86 virtual void drawPaint(const SkPaint& paint) OVERRIDE { 87 AutoStamper stamper(this); 88 SkProxyCanvas::drawPaint(paint); 89 } 90 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 97 virtual void drawOval(const SkRect& rect, const SkPaint& paint) OVERRIDE { 98 AutoStamper stamper(this); 99 SkProxyCanvas::drawOval(rect, paint); 100 } 101 102 virtual void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE { 103 AutoStamper stamper(this); 104 SkProxyCanvas::drawRect(rect, paint); 105 } 106 107 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint) OVERRIDE { 108 AutoStamper stamper(this); 109 SkProxyCanvas::drawRRect(rrect, paint); 110 } 111 112 virtual void drawPath(const SkPath& path, const SkPaint& paint) OVERRIDE { 113 AutoStamper stamper(this); 114 SkProxyCanvas::drawPath(path, paint); 115 } 116 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 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 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 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 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 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 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 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 170 virtual void drawPicture(SkPicture& picture) OVERRIDE { 171 AutoStamper stamper(this); 172 SkProxyCanvas::drawPicture(picture); 173 } 174 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 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 200 AutoStamper::AutoStamper(TimingCanvas *timing_canvas) 201 : timing_canvas_(timing_canvas) { 202 start_ticks_ = base::TimeTicks::HighResNow(); 203 } 204 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 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 221 BenchmarkingCanvas::~BenchmarkingCanvas() { 222 removeAll(); 223 } 224 225 size_t BenchmarkingCanvas::CommandCount() const { 226 return debug_canvas_->getSize(); 227 } 228 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 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