diff options
Diffstat (limited to 'skia')
-rw-r--r-- | skia/ext/analysis_canvas.cc | 129 | ||||
-rw-r--r-- | skia/ext/analysis_canvas_unittest.cc | 13 |
2 files changed, 101 insertions, 41 deletions
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc index 6a07d40..93580b0 100644 --- a/skia/ext/analysis_canvas.cc +++ b/skia/ext/analysis_canvas.cc @@ -13,16 +13,24 @@ namespace { -// FIXME: Arbitrary number. Requires tuning & experimentation. +// FIXME: Arbitrary numbers. Requires tuning & experimentation. // Probably requires per-platform tuning; N10 average draw call takes // 25x as long as Z620. const int gPictureCostThreshold = 1000; +const int kUnknownExpensiveCost = 500; +const int kUnknownBitmapCost = 1000; // URI label for a lazily decoded SkPixelRef. const char kLabelLazyDecoded[] = "lazy"; const int kLabelLazyDecodedLength = 4; -static bool isSolidColorPaint(const SkPaint& paint) { +// Estimate of rasterization performance on mid-low-range hardware, +// drawing rectangles with simple paints. +const int kSimpleRectPixelsPerUS = 1000; +const int kComplexRectPixelsPerUS = 100; +const int kSimpleTextCharPerUS = 2; + +bool isSolidColorPaint(const SkPaint& paint) { SkXfermode::Mode xferMode; // getXfermode can return a NULL, but that is handled @@ -43,9 +51,9 @@ static bool isSolidColorPaint(const SkPaint& paint) { xferMode == SkXfermode::kSrcOver_Mode)); } -static bool isFullQuad(const SkDraw& draw, - const SkRect& canvasRect, - const SkRect& drawnRect) { +bool isFullQuad(const SkDraw& draw, + const SkRect& canvasRect, + const SkRect& drawnRect) { // If the transform results in a non-axis aligned // rect, then be conservative and return false. @@ -72,6 +80,12 @@ static bool isFullQuad(const SkDraw& draw, drawBitmapRect.contains(canvasRect); } +bool hasBitmap(const SkPaint& paint) { + SkShader* shader = paint.getShader(); + return shader && + (SkShader::kNone_BitmapType != shader->asABitmap(NULL, NULL, NULL)); +} + } // namespace namespace skia { @@ -163,7 +177,8 @@ void AnalysisDevice::consumeLazyPixelRefs(LazyPixelRefList* pixelRefs) { } void AnalysisDevice::clear(SkColor color) { - ++estimatedCost_; + // FIXME: cost here should be simple rect of device size + estimatedCost_ += kUnknownExpensiveCost; isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0); @@ -177,30 +192,40 @@ void AnalysisDevice::clear(SkColor color) { } void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += kUnknownExpensiveCost; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count, const SkPoint[], const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += kUnknownExpensiveCost; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect, const SkPaint& paint) { // FIXME: if there's a pending image decode & resize, more expensive + estimatedCost_ += 1 + rect.width() * rect.height() / kSimpleRectPixelsPerUS; if (paint.getMaskFilter()) { - estimatedCost_ += 300; + estimatedCost_ += kUnknownExpensiveCost; } - ++estimatedCost_; - addBitmapFromPaint(paint); + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } + bool doesCoverCanvas = isFullQuad(draw, SkRect::MakeWH(width(), height()), rect); @@ -245,15 +270,18 @@ void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect, void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += kUnknownExpensiveCost; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, const SkPaint& paint, - const SkMatrix* prePathMatrix , + const SkMatrix* prePathMatrix, bool pathIsMutable ) { // On Z620, every antialiased path costs us about 300us. // We've only seen this in practice on filled paths, but @@ -261,16 +289,23 @@ void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, if (paint.getMaskFilter()) { estimatedCost_ += 300; } - ++estimatedCost_; + // FIXME: horrible overestimate if the path is stroked instead of filled + estimatedCost_ += 1 + path.getBounds().width() * + path.getBounds().height() / kSimpleRectPixelsPerUS; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, const SkIRect* srcRectOrNull, const SkMatrix& matrix, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += kUnknownExpensiveCost; + //DCHECK(hasBitmap(paint)); + estimatedCost_ += kUnknownBitmapCost; isSolidColor_ = false; isTransparent_ = false; addBitmap(bitmap); @@ -278,7 +313,9 @@ void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += kUnknownExpensiveCost; + //DCHECK(hasBitmap(paint)); + estimatedCost_ += kUnknownBitmapCost; isSolidColor_ = false; isTransparent_ = false; addBitmap(bitmap); @@ -287,7 +324,10 @@ void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, const SkRect* srcOrNull, const SkRect& dst, const SkPaint& paint) { - ++estimatedCost_; + // FIXME: we also accumulate cost from drawRect() + estimatedCost_ += 1 + dst.width() * dst.height() / kComplexRectPixelsPerUS; + //DCHECK(hasBitmap(paint)); + estimatedCost_ += kUnknownBitmapCost; // Call drawRect to determine transparency, // but reset solid color to false. @@ -299,30 +339,41 @@ void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += 1 + len / kSimpleTextCharPerUS; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } -void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t len, +void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, + size_t len, const SkScalar pos[], SkScalar constY, int scalarsPerPos, const SkPaint& paint) { // FIXME: On Z620, every glyph cache miss costs us about 10us. // We don't have a good mechanism for predicting glyph cache misses. - ++estimatedCost_; + estimatedCost_ += 1 + len / kSimpleTextCharPerUS; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } -void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, +void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, + size_t len, const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += 1 + len / kSimpleTextCharPerUS; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } #ifdef SK_BUILD_FOR_ANDROID @@ -330,10 +381,13 @@ void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, size_t len, const SkPoint pos[], const SkPaint& paint, const SkPath& path, const SkMatrix* matrix) { - ++estimatedCost_; + estimatedCost_ += 1 + len / kSimpleTextCharPerUS; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } #endif @@ -343,15 +397,20 @@ void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) { - ++estimatedCost_; + estimatedCost_ += kUnknownExpensiveCost; + if (hasBitmap(paint)) { + estimatedCost_ += kUnknownBitmapCost; + addBitmapFromPaint(paint); + } isSolidColor_ = false; isTransparent_ = false; - addBitmapFromPaint(paint); } void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y, - const SkPaint&) { - ++estimatedCost_; + const SkPaint& paint) { + estimatedCost_ += kUnknownExpensiveCost; + if (hasBitmap(paint)) + estimatedCost_ += kUnknownBitmapCost; isSolidColor_ = false; isTransparent_ = false; } diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc index 1623732..f403a59 100644 --- a/skia/ext/analysis_canvas_unittest.cc +++ b/skia/ext/analysis_canvas_unittest.cc @@ -46,7 +46,8 @@ class TestShader : public SkShader { SkShader::BitmapType asABitmap(SkBitmap* bitmap, SkMatrix*, TileMode xy[2]) const { - *bitmap = *bitmap_; + if (bitmap) + *bitmap = *bitmap_; return SkShader::kDefault_BitmapType; } @@ -92,7 +93,7 @@ TEST(AnalysisCanvasTest, ClearCanvas) { EXPECT_TRUE(canvas.getColorIfSolid(&outputColor)); EXPECT_FALSE(canvas.isTransparent()); - EXPECT_TRUE(canvas.isCheap()); + EXPECT_FALSE(canvas.isCheap()); EXPECT_EQ(outputColor, color); // Translucent color @@ -101,7 +102,7 @@ TEST(AnalysisCanvasTest, ClearCanvas) { EXPECT_FALSE(canvas.getColorIfSolid(&outputColor)); EXPECT_FALSE(canvas.isTransparent()); - EXPECT_TRUE(canvas.isCheap()); + EXPECT_FALSE(canvas.isCheap()); // Test helper methods solidColorFill(canvas); @@ -145,7 +146,7 @@ TEST(AnalysisCanvasTest, ComplexActions) { EXPECT_FALSE(canvas.getColorIfSolid(&outputColor)); EXPECT_FALSE(canvas.isTransparent()); - EXPECT_TRUE(canvas.isCheap()); + EXPECT_FALSE(canvas.isCheap()); // Draw oval test. solidColorFill(canvas); @@ -153,7 +154,7 @@ TEST(AnalysisCanvasTest, ComplexActions) { EXPECT_FALSE(canvas.getColorIfSolid(&outputColor)); EXPECT_FALSE(canvas.isTransparent()); - EXPECT_TRUE(canvas.isCheap()); + EXPECT_FALSE(canvas.isCheap()); // Draw bitmap test. solidColorFill(canvas); @@ -163,7 +164,7 @@ TEST(AnalysisCanvasTest, ComplexActions) { EXPECT_FALSE(canvas.getColorIfSolid(&outputColor)); EXPECT_FALSE(canvas.isTransparent()); - EXPECT_TRUE(canvas.isCheap()); + EXPECT_FALSE(canvas.isCheap()); } TEST(AnalysisCanvasTest, SimpleDrawRect) { |