Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/debug/trace_event.h" | 5 #include "base/debug/trace_event.h" |
| 6 #include "skia/ext/analysis_canvas.h" | 6 #include "skia/ext/analysis_canvas.h" |
| 7 #include "third_party/skia/include/core/SkDevice.h" | 7 #include "third_party/skia/include/core/SkDevice.h" |
| 8 #include "third_party/skia/include/core/SkDraw.h" | 8 #include "third_party/skia/include/core/SkDraw.h" |
| 9 #include "third_party/skia/include/core/SkRRect.h" | 9 #include "third_party/skia/include/core/SkRRect.h" |
| 10 #include "third_party/skia/include/core/SkShader.h" | |
| 10 #include "third_party/skia/src/core/SkRasterClip.h" | 11 #include "third_party/skia/src/core/SkRasterClip.h" |
| 11 #include "ui/gfx/rect_conversions.h" | 12 #include "ui/gfx/rect_conversions.h" |
| 12 | 13 |
| 13 namespace { | 14 namespace { |
| 14 | 15 |
| 15 // FIXME: Arbitrary number. Requires tuning & experimentation. | 16 // FIXME: Arbitrary number. Requires tuning & experimentation. |
| 16 // Probably requires per-platform tuning; N10 average draw call takes | 17 // Probably requires per-platform tuning; N10 average draw call takes |
| 17 // 25x as long as Z620. | 18 // 25x as long as Z620. |
| 18 const int gPictureCostThreshold = 1000; | 19 const int gPictureCostThreshold = 1000; |
| 19 | 20 |
| 21 // URI label for a lazily decoded SkPixelRef. | |
| 22 const char labelLazyDecoded[] = "lazy"; | |
|
Sami
2013/03/18 12:14:33
const char kLabelLazyDecoded[] = ...
| |
| 23 | |
| 20 static bool isSolidColorPaint(const SkPaint& paint) { | 24 static bool isSolidColorPaint(const SkPaint& paint) { |
| 21 SkXfermode::Mode xferMode; | 25 SkXfermode::Mode xferMode; |
| 22 | 26 |
| 23 // getXfermode can return a NULL, but that is handled | 27 // getXfermode can return a NULL, but that is handled |
| 24 // gracefully by AsMode (NULL turns into kSrcOver mode). | 28 // gracefully by AsMode (NULL turns into kSrcOver mode). |
| 25 SkXfermode::AsMode(paint.getXfermode(), &xferMode); | 29 SkXfermode::AsMode(paint.getXfermode(), &xferMode); |
| 26 | 30 |
| 27 // Paint is solid color if the following holds: | 31 // Paint is solid color if the following holds: |
| 28 // - Alpha is 1.0, style is fill, and there are no special effects | 32 // - Alpha is 1.0, style is fill, and there are no special effects |
| 29 // - Xfer mode is either kSrc or kSrcOver (kSrcOver is equivalent | 33 // - Xfer mode is either kSrc or kSrcOver (kSrcOver is equivalent |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 if (isForcedNotSolid_) | 108 if (isForcedNotSolid_) |
| 105 isSolidColor_ = false; | 109 isSolidColor_ = false; |
| 106 } | 110 } |
| 107 | 111 |
| 108 void AnalysisDevice::setForceNotTransparent(bool flag) { | 112 void AnalysisDevice::setForceNotTransparent(bool flag) { |
| 109 isForcedNotTransparent_ = flag; | 113 isForcedNotTransparent_ = flag; |
| 110 if (isForcedNotTransparent_) | 114 if (isForcedNotTransparent_) |
| 111 isTransparent_ = false; | 115 isTransparent_ = false; |
| 112 } | 116 } |
| 113 | 117 |
| 118 void AnalysisDevice::addPixelRefIfLazy(SkPixelRef* pixelRef) { | |
| 119 if (!pixelRef) | |
| 120 return; | |
| 121 | |
| 122 uint32_t genID = pixelRef->getGenerationID(); | |
| 123 | |
| 124 // If this ID exists (whether it is lazy pixel ref or not), | |
| 125 // we can return early. | |
| 126 std::pair<base::hash_set<uint32_t>::iterator, bool> insertionResult = | |
| 127 existingPixelRefIDs_.insert(genID); | |
| 128 if (!insertionResult.second) | |
| 129 return; | |
| 130 | |
| 131 if (pixelRef->getURI() && | |
| 132 !strncmp(pixelRef->getURI(), labelLazyDecoded, 4)) { | |
|
Sami
2013/03/18 12:14:33
Use a named constant instead of 4.
| |
| 133 lazyPixelRefs_.push_back(static_cast<skia::LazyPixelRef*>(pixelRef)); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 void AnalysisDevice::addBitmap(const SkBitmap& bitmap) { | |
| 138 addPixelRefIfLazy(bitmap.pixelRef()); | |
| 139 } | |
| 140 | |
| 141 void AnalysisDevice::addBitmapFromPaint(const SkPaint& paint) { | |
| 142 SkShader* shader = paint.getShader(); | |
| 143 if (shader) { | |
| 144 SkBitmap bitmap; | |
| 145 // Check whether the shader is a gradient in order to short-circuit | |
| 146 // call to asABitmap to prevent generation of bitmaps from | |
| 147 // gradient shaders, which implement asABitmap. | |
| 148 if (SkShader::kNone_GradientType == shader->asAGradient(NULL) && | |
| 149 SkShader::kNone_BitmapType != shader->asABitmap(&bitmap, NULL, NULL)) { | |
| 150 addPixelRefIfLazy(bitmap.pixelRef()); | |
| 151 } | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 void AnalysisDevice::consumeLazyPixelRefs(std::list<LazyPixelRef*>& pixelRefs) { | |
| 156 DCHECK(pixelRefs.empty()); | |
| 157 lazyPixelRefs_.swap(pixelRefs); | |
| 158 existingPixelRefIDs_.clear(); | |
| 159 } | |
| 160 | |
| 114 void AnalysisDevice::clear(SkColor color) { | 161 void AnalysisDevice::clear(SkColor color) { |
| 115 ++estimatedCost_; | 162 ++estimatedCost_; |
| 116 | 163 |
| 117 isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0); | 164 isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0); |
| 118 | 165 |
| 119 if (!isForcedNotSolid_ && SkColorGetA(color) == 255) { | 166 if (!isForcedNotSolid_ && SkColorGetA(color) == 255) { |
| 120 isSolidColor_ = true; | 167 isSolidColor_ = true; |
| 121 color_ = color; | 168 color_ = color; |
| 122 } | 169 } |
| 123 else { | 170 else { |
| 124 isSolidColor_ = false; | 171 isSolidColor_ = false; |
| 125 } | 172 } |
| 126 } | 173 } |
| 127 | 174 |
| 128 void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) { | 175 void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) { |
| 129 ++estimatedCost_; | 176 ++estimatedCost_; |
| 130 isSolidColor_ = false; | 177 isSolidColor_ = false; |
| 131 isTransparent_ = false; | 178 isTransparent_ = false; |
| 179 addBitmapFromPaint(paint); | |
|
Tom Hudson
2013/03/18 11:52:39
Hmm, idiomatically this isn't how I expected drawP
| |
| 132 } | 180 } |
| 133 | 181 |
| 134 void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, | 182 void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, |
| 135 size_t count, const SkPoint[], | 183 size_t count, const SkPoint[], |
| 136 const SkPaint& paint) { | 184 const SkPaint& paint) { |
| 137 ++estimatedCost_; | 185 ++estimatedCost_; |
| 138 isSolidColor_ = false; | 186 isSolidColor_ = false; |
| 139 isTransparent_ = false; | 187 isTransparent_ = false; |
| 188 addBitmapFromPaint(paint); | |
| 140 } | 189 } |
| 141 | 190 |
| 142 void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect, | 191 void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect, |
| 143 const SkPaint& paint) { | 192 const SkPaint& paint) { |
| 144 | 193 |
| 145 // FIXME: if there's a pending image decode & resize, more expensive | 194 // FIXME: if there's a pending image decode & resize, more expensive |
| 146 if (paint.getMaskFilter()) { | 195 if (paint.getMaskFilter()) { |
| 147 estimatedCost_ += 300; | 196 estimatedCost_ += 300; |
| 148 } | 197 } |
| 149 ++estimatedCost_; | 198 ++estimatedCost_; |
| 150 | 199 addBitmapFromPaint(paint); |
| 151 bool doesCoverCanvas = isFullQuad(draw, | 200 bool doesCoverCanvas = isFullQuad(draw, |
| 152 SkRect::MakeWH(width(), height()), | 201 SkRect::MakeWH(width(), height()), |
| 153 rect); | 202 rect); |
| 154 | 203 |
| 155 SkXfermode::Mode xferMode; | 204 SkXfermode::Mode xferMode; |
| 156 SkXfermode::AsMode(paint.getXfermode(), &xferMode); | 205 SkXfermode::AsMode(paint.getXfermode(), &xferMode); |
| 157 | 206 |
| 158 // This canvas will become transparent if the following holds: | 207 // This canvas will become transparent if the following holds: |
| 159 // - The quad is a full tile quad | 208 // - The quad is a full tile quad |
| 160 // - We're not in "forced not transparent" mode | 209 // - We're not in "forced not transparent" mode |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 188 else { | 237 else { |
| 189 isSolidColor_ = false; | 238 isSolidColor_ = false; |
| 190 } | 239 } |
| 191 } | 240 } |
| 192 | 241 |
| 193 void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval, | 242 void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval, |
| 194 const SkPaint& paint) { | 243 const SkPaint& paint) { |
| 195 ++estimatedCost_; | 244 ++estimatedCost_; |
| 196 isSolidColor_ = false; | 245 isSolidColor_ = false; |
| 197 isTransparent_ = false; | 246 isTransparent_ = false; |
| 247 addBitmapFromPaint(paint); | |
| 198 } | 248 } |
| 199 | 249 |
| 200 void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, | 250 void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, |
| 201 const SkPaint& paint, | 251 const SkPaint& paint, |
| 202 const SkMatrix* prePathMatrix , | 252 const SkMatrix* prePathMatrix , |
| 203 bool pathIsMutable ) { | 253 bool pathIsMutable ) { |
| 204 // On Z620, every antialiased path costs us about 300us. | 254 // On Z620, every antialiased path costs us about 300us. |
| 205 // We've only seen this in practice on filled paths, but | 255 // We've only seen this in practice on filled paths, but |
| 206 // we expect it to apply to all path stroking modes. | 256 // we expect it to apply to all path stroking modes. |
| 207 if (paint.getMaskFilter()) { | 257 if (paint.getMaskFilter()) { |
| 208 estimatedCost_ += 300; | 258 estimatedCost_ += 300; |
| 209 } | 259 } |
| 210 ++estimatedCost_; | 260 ++estimatedCost_; |
| 211 isSolidColor_ = false; | 261 isSolidColor_ = false; |
| 212 isTransparent_ = false; | 262 isTransparent_ = false; |
| 263 addBitmapFromPaint(paint); | |
| 213 } | 264 } |
| 214 | 265 |
| 215 void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, | 266 void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, |
| 216 const SkIRect* srcRectOrNull, | 267 const SkIRect* srcRectOrNull, |
| 217 const SkMatrix& matrix, const SkPaint& paint) { | 268 const SkMatrix& matrix, const SkPaint& paint) { |
| 218 ++estimatedCost_; | 269 ++estimatedCost_; |
| 219 isSolidColor_ = false; | 270 isSolidColor_ = false; |
| 220 isTransparent_ = false; | 271 isTransparent_ = false; |
| 272 addBitmap(bitmap); | |
| 221 } | 273 } |
| 222 | 274 |
| 223 void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, | 275 void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, |
| 224 int x, int y, const SkPaint& paint) { | 276 int x, int y, const SkPaint& paint) { |
| 225 ++estimatedCost_; | 277 ++estimatedCost_; |
| 226 isSolidColor_ = false; | 278 isSolidColor_ = false; |
| 227 isTransparent_ = false; | 279 isTransparent_ = false; |
| 280 addBitmap(bitmap); | |
| 228 } | 281 } |
| 229 | 282 |
| 230 void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap&, | 283 void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, |
| 231 const SkRect* srcOrNull, const SkRect& dst, | 284 const SkRect* srcOrNull, const SkRect& dst, |
| 232 const SkPaint& paint) { | 285 const SkPaint& paint) { |
| 233 ++estimatedCost_; | 286 ++estimatedCost_; |
| 234 | 287 |
| 235 // Call drawRect to determine transparency, | 288 // Call drawRect to determine transparency, |
| 236 // but reset solid color to false. | 289 // but reset solid color to false. |
| 237 drawRect(draw, dst, paint); | 290 drawRect(draw, dst, paint); |
| 238 isSolidColor_ = false; | 291 isSolidColor_ = false; |
| 292 addBitmap(bitmap); | |
| 239 } | 293 } |
| 240 | 294 |
| 241 | 295 |
| 242 void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len, | 296 void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len, |
| 243 SkScalar x, SkScalar y, const SkPaint& paint) { | 297 SkScalar x, SkScalar y, const SkPaint& paint) { |
| 244 ++estimatedCost_; | 298 ++estimatedCost_; |
| 245 isSolidColor_ = false; | 299 isSolidColor_ = false; |
| 246 isTransparent_ = false; | 300 isTransparent_ = false; |
| 301 addBitmapFromPaint(paint); | |
| 247 } | 302 } |
| 248 | 303 |
| 249 void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n, | 304 void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n, |
| 250 const SkScalar pos[], SkScalar constY, | 305 const SkScalar pos[], SkScalar constY, |
| 251 int scalarsPerPos, const SkPaint& paint) { | 306 int scalarsPerPos, const SkPaint& paint) { |
| 252 // FIXME: On Z620, every glyph cache miss costs us about 10us. | 307 // FIXME: On Z620, every glyph cache miss costs us about 10us. |
| 253 // We don't have a good mechanism for predicting glyph cache misses. | 308 // We don't have a good mechanism for predicting glyph cache misses. |
| 254 ++estimatedCost_; | 309 ++estimatedCost_; |
| 255 isSolidColor_ = false; | 310 isSolidColor_ = false; |
| 256 isTransparent_ = false; | 311 isTransparent_ = false; |
| 312 addBitmapFromPaint(paint); | |
| 257 } | 313 } |
| 258 | 314 |
| 259 void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, | 315 void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, |
| 260 const SkPath& path, const SkMatrix* matrix, | 316 const SkPath& path, const SkMatrix* matrix, |
| 261 const SkPaint& paint) { | 317 const SkPaint& paint) { |
| 262 ++estimatedCost_; | 318 ++estimatedCost_; |
| 263 isSolidColor_ = false; | 319 isSolidColor_ = false; |
| 264 isTransparent_ = false; | 320 isTransparent_ = false; |
| 321 addBitmapFromPaint(paint); | |
| 265 } | 322 } |
| 266 | 323 |
| 267 #ifdef SK_BUILD_FOR_ANDROID | 324 #ifdef SK_BUILD_FOR_ANDROID |
| 268 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, | 325 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, |
| 269 size_t len, | 326 size_t len, |
| 270 const SkPoint pos[], const SkPaint& paint, | 327 const SkPoint pos[], const SkPaint& paint, |
| 271 const SkPath& path, const SkMatrix* matrix) { | 328 const SkPath& path, const SkMatrix* matrix) { |
| 272 ++estimatedCost_; | 329 ++estimatedCost_; |
| 273 isSolidColor_ = false; | 330 isSolidColor_ = false; |
| 274 isTransparent_ = false; | 331 isTransparent_ = false; |
| 332 addBitmapFromPaint(paint); | |
| 275 } | 333 } |
| 276 #endif | 334 #endif |
| 277 | 335 |
| 278 void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, | 336 void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, |
| 279 int vertexCount, | 337 int vertexCount, |
| 280 const SkPoint verts[], const SkPoint texs[], | 338 const SkPoint verts[], const SkPoint texs[], |
| 281 const SkColor colors[], SkXfermode* xmode, | 339 const SkColor colors[], SkXfermode* xmode, |
| 282 const uint16_t indices[], int indexCount, | 340 const uint16_t indices[], int indexCount, |
| 283 const SkPaint& paint) { | 341 const SkPaint& paint) { |
| 284 ++estimatedCost_; | 342 ++estimatedCost_; |
| 285 isSolidColor_ = false; | 343 isSolidColor_ = false; |
| 286 isTransparent_ = false; | 344 isTransparent_ = false; |
| 345 addBitmapFromPaint(paint); | |
| 287 } | 346 } |
| 288 | 347 |
| 289 void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y, | 348 void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y, |
| 290 const SkPaint&) { | 349 const SkPaint&) { |
| 291 ++estimatedCost_; | 350 ++estimatedCost_; |
| 292 isSolidColor_ = false; | 351 isSolidColor_ = false; |
| 293 isTransparent_ = false; | 352 isTransparent_ = false; |
| 294 } | 353 } |
| 295 | 354 |
| 296 | 355 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 316 } | 375 } |
| 317 | 376 |
| 318 bool AnalysisCanvas::isTransparent() const { | 377 bool AnalysisCanvas::isTransparent() const { |
| 319 return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent(); | 378 return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent(); |
| 320 } | 379 } |
| 321 | 380 |
| 322 int AnalysisCanvas::getEstimatedCost() const { | 381 int AnalysisCanvas::getEstimatedCost() const { |
| 323 return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost(); | 382 return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost(); |
| 324 } | 383 } |
| 325 | 384 |
| 385 void AnalysisCanvas::consumeLazyPixelRefs(std::list<LazyPixelRef*>& pixelRefs) { | |
| 386 static_cast<AnalysisDevice*>(getDevice())->consumeLazyPixelRefs(pixelRefs); | |
| 387 } | |
| 388 | |
| 326 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, | 389 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, |
| 327 bool doAA) { | 390 bool doAA) { |
| 328 return INHERITED::clipRect(rect, op, doAA); | 391 return INHERITED::clipRect(rect, op, doAA); |
| 329 } | 392 } |
| 330 | 393 |
| 331 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op, | 394 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op, |
| 332 bool doAA) { | 395 bool doAA) { |
| 333 // clipPaths can make our calls to isFullQuad invalid (ie have false | 396 // clipPaths can make our calls to isFullQuad invalid (ie have false |
| 334 // positives). As a precaution, force the setting to be non-solid | 397 // positives). As a precaution, force the setting to be non-solid |
| 335 // and non-transparent until we pop this | 398 // and non-transparent until we pop this |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 if (savedStackSize_ < forceNotTransparentStackLevel_) { | 481 if (savedStackSize_ < forceNotTransparentStackLevel_) { |
| 419 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(false) ; | 482 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(false) ; |
| 420 forceNotTransparentStackLevel_ = kNoLayer; | 483 forceNotTransparentStackLevel_ = kNoLayer; |
| 421 } | 484 } |
| 422 } | 485 } |
| 423 } | 486 } |
| 424 | 487 |
| 425 } // namespace skia | 488 } // namespace skia |
| 426 | 489 |
| 427 | 490 |
| OLD | NEW |