Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(530)

Unified Diff: skia/ext/analysis_canvas.cc

Issue 12316084: cc: Consolidate the analysis_canvas operations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed unittest Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« cc/tile_manager.cc ('K') | « skia/ext/analysis_canvas.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: skia/ext/analysis_canvas.cc
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc
index 72b9eeb987bdc07adf74c3a2f6b0f5cdbe5b6faf..22c2839168f2b1d4f58e5388ebfb82dfac3b18b5 100644
--- a/skia/ext/analysis_canvas.cc
+++ b/skia/ext/analysis_canvas.cc
@@ -7,6 +7,7 @@
#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkDraw.h"
#include "third_party/skia/include/core/SkRRect.h"
+#include "third_party/skia/src/core/SkRasterClip.h"
#include "ui/gfx/rect_conversions.h"
namespace {
@@ -16,50 +17,169 @@ namespace {
// 25x as long as Z620.
const int gPictureCostThreshold = 1000;
+static bool isSolidColorPaint(const SkPaint& paint) {
+ SkXfermode::Mode xferMode;
+
+ // getXfermode can return a NULL, but that is handled
+ // gracefully by AsMode (NULL turns into kSrcOver mode).
+ SkXfermode::AsMode(paint.getXfermode(), &xferMode);
+
+ // Paint is solid color if the following holds:
+ // - Alpha is 1.0, style is fill, and there are no special effects
+ // - Xfer mode is either kSrc or kSrcOver (kSrcOver is equivalent
+ // to kSrc if source alpha is 1.0, which is already checked).
+ return (paint.getAlpha() == 255 &&
+ !paint.getShader() &&
+ !paint.getLooper() &&
+ !paint.getMaskFilter() &&
+ !paint.getColorFilter() &&
+ paint.getStyle() == SkPaint::kFill_Style &&
+ (xferMode == SkXfermode::kSrc_Mode ||
+ xferMode == SkXfermode::kSrcOver_Mode));
}
+} // namespace
+
namespace skia {
AnalysisDevice::AnalysisDevice(const SkBitmap& bm)
: INHERITED(bm)
- , estimatedCost_(0) {
+ , estimatedCost_(0)
+ , isForcedNotSolid_(false)
+ , isForcedNotTransparent_(false)
+ , isSolidColor_(false)
+ , isTransparent_(false) {
}
AnalysisDevice::~AnalysisDevice() {
-
Tom Hudson 2013/02/27 14:49:36 Nit: Is this whitespace change dictated by the Chr
}
int AnalysisDevice::getEstimatedCost() const {
return estimatedCost_;
}
+bool AnalysisDevice::getColorIfSolid(SkColor* color) const {
+ if (isSolidColor_)
+ *color = color_;
+ return isSolidColor_;
+}
+
+bool AnalysisDevice::isTransparent() const {
+ return isTransparent_;
+}
+
+void AnalysisDevice::setForceNotSolid(bool flag) {
+ isForcedNotSolid_ = flag;
+ if (isForcedNotSolid_)
+ isSolidColor_ = false;
+}
+
+void AnalysisDevice::setForceNotTransparent(bool flag) {
+ isForcedNotTransparent_ = flag;
+ if (isForcedNotTransparent_)
+ isTransparent_ = false;
+}
+
void AnalysisDevice::clear(SkColor color) {
- ++estimatedCost_;
+ ++estimatedCost_;
+
+ isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0);
+
+ if (!isForcedNotSolid_ && SkColorGetA(color) == 255) {
+ isSolidColor_ = true;
+ color_ = color;
+ }
+ else {
+ isSolidColor_ = false;
+ }
}
void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode,
size_t count, const SkPoint[],
const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
-void AnalysisDevice::drawRect(const SkDraw&, const SkRect& r,
+void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
const SkPaint& paint) {
+
// FIXME: if there's a pending image decode & resize, more expensive
if (paint.getMaskFilter()) {
estimatedCost_ += 300;
}
++estimatedCost_;
+
+ SkRect drawBitmapRect;
+ draw.fBitmap->getBounds(&drawBitmapRect);
+ SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
+ SkRect canvasRect = SkRect::MakeWH(width(), height());
+ SkRect deviceRect;
+ draw.fMatrix->mapRect(&deviceRect, rect);
+
+
+ // This draw is equivalent to clear(), if the following conditions hold:
+ // - Clip rect is an actual rectangle.
+ // - The rect we're drawing (post-transform) contains the clip rect.
+ // That is, all of clip rect will be colored by the rect.
+ // - Clip rect contains the canvas rect.
+ // That is, we're not clipping to a portion of this canvas.
+ bool isFullQuad = (draw.fRC->isRect() &&
+ deviceRect.contains(clipRect) &&
+ clipRect.contains(canvasRect) &&
+ drawBitmapRect.contains(canvasRect));
+
+ SkXfermode::Mode xferMode;
+ SkXfermode::AsMode(paint.getXfermode(), &xferMode);
+
+ // This canvas will become transparent if the following holds:
+ // - The quad is a full tile quad
+ // - We're not in "forced not transparent" mode
+ // - Transfer mode is clear (0 color, 0 alpha)
+ //
+ // If the paint alpha is not 0, or if the transfrer mode is
+ // not src, then this canvas will not be transparent.
+ //
+ // In all other cases, we keep the current transparent value
+ if (isFullQuad &&
+ !isForcedNotTransparent_ &&
+ xferMode == SkXfermode::kClear_Mode) {
+ isTransparent_ = true;
+ }
+ else if (paint.getAlpha() != 0 ||
+ xferMode != SkXfermode::kSrc_Mode) {
+ isTransparent_ = false;
+ }
+
+ // This bitmap is solid if and only if the following holds.
+ // Note that this might be overly conservative:
+ // - We're not in "forced not solid" mode
+ // - Paint is solid color
+ // - The quad is a full tile quad
+ if (!isForcedNotSolid_ &&
+ isSolidColorPaint(paint) &&
+ isFullQuad) {
+ isSolidColor_ = true;
+ color_ = paint.getColor();
+ }
+ else {
+ isSolidColor_ = false;
+ }
}
void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval,
const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path,
@@ -73,31 +193,78 @@ void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path,
estimatedCost_ += 300;
}
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
const SkIRect* srcRectOrNull,
- const SkMatrix& matrix, const SkPaint& paint)
- {
+ const SkMatrix& matrix, const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
int x, int y, const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
-void AnalysisDevice::drawBitmapRect(const SkDraw&, const SkBitmap&,
- const SkRect* srcOrNull, const SkRect& dst,
+void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap&,
+ const SkRect* srcOrNull, const SkRect& rect,
Tom Hudson 2013/02/27 14:49:36 Nit: I think you've changed this parameter name fr
const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+
+ SkRect drawBitmapRect;
+ draw.fBitmap->getBounds(&drawBitmapRect);
+ SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
+ SkRect bitmapRect = SkRect::MakeWH(width(), height());
+ SkRect deviceRect;
+ draw.fMatrix->mapRect(&deviceRect, rect);
+
+ // This draw is equivalent to clear(), if the following conditions hold:
Tom Hudson 2013/02/27 14:49:36 Both of these clauses are duplicated from drawRect
+ // - Clip rect is an actual rectangle.
+ // - The rect we're drawing (post-transform) contains the clip rect.
+ // That is, all of clip rect will be colored by the rect.
+ // - Clip rect contains the canvas rect.
+ // That is, we're not clipping to a portion of this canvas.
+ bool isFullQuad = (draw.fRC->isRect() &&
+ deviceRect.contains(clipRect) &&
+ clipRect.contains(bitmapRect) &&
+ drawBitmapRect.contains(bitmapRect));
+
+ SkXfermode::Mode xferMode;
+ SkXfermode::AsMode(paint.getXfermode(), &xferMode);
+
+ // This canvas will become transparent if the following holds:
+ // - The quad is a full tile quad
+ // - We're not in "forced not transparent" mode
+ // - Transfer mode is clear (0 color, 0 alpha)
+ //
+ // If the paint alpha is not 0, or if the transfrer mode is
+ // not src, then this canvas will not be transparent.
+ //
+ // In all other cases, we keep the current transparent value
+ if (isFullQuad &&
+ !isForcedNotTransparent_ &&
+ xferMode == SkXfermode::kClear_Mode) {
+ isTransparent_ = true;
+ }
+ else if (paint.getAlpha() != 0 ||
+ xferMode != SkXfermode::kSrc_Mode) {
+ isTransparent_ = false;
+ }
}
void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len,
- SkScalar x, SkScalar y, const SkPaint& paint)
- {
+ SkScalar x, SkScalar y, const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t len,
@@ -106,21 +273,26 @@ void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le
// FIXME: On Z620, every glyph cache miss costs us about 10us.
// We don't have a good mechanism for predicting glyph cache misses.
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
#ifdef SK_BUILD_FOR_ANDROID
void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text,
size_t len,
const SkPoint pos[], const SkPaint& paint,
- const SkPath& path, const SkMatrix* matrix)
- {
+ const SkPath& path, const SkMatrix* matrix) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
#endif
@@ -131,19 +303,22 @@ void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&) {
++estimatedCost_;
+ isSolidColor_ = false;
+ isTransparent_ = false;
}
-
AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device)
- : INHERITED(device) {
-
+ : INHERITED(device)
+ , savedLayerStackSize_(0) {
}
AnalysisCanvas::~AnalysisCanvas() {
@@ -154,11 +329,18 @@ bool AnalysisCanvas::isCheap() const {
return getEstimatedCost() < gPictureCostThreshold;
}
+bool AnalysisCanvas::getColorIfSolid(SkColor* color) const {
+ return (static_cast<AnalysisDevice*>(getDevice()))->getColorIfSolid(color);
+}
+
+bool AnalysisCanvas::isTransparent() const {
+ return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent();
+}
+
int AnalysisCanvas::getEstimatedCost() const {
return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost();
}
-
bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op,
bool doAA) {
return INHERITED::clipRect(rect, op, doAA);
@@ -174,17 +356,49 @@ bool AnalysisCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op,
return INHERITED::clipRect(rrect.getBounds(), op, doAA);
}
-int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint*,
+int AnalysisCanvas::save(SkCanvas::SaveFlags flags) {
+ INHERITED::save(flags);
+}
+
+int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
SkCanvas::SaveFlags flags) {
+ // If after we draw to the saved layer, we have to blend with the current
+ // layer, then we can conservatively say that the canvas will not be of
+ // solid color.
Tom Hudson 2013/02/27 14:49:36 Thanks for adding these explanations.
+ if ((paint && !isSolidColorPaint(*paint)) ||
+ (bounds && !bounds->contains(
+ SkRect::MakeWH(getDevice()->width(), getDevice()->height()))))
+ (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(true);
+
+ // If after we draw to the save layer, we have to blend with the current
+ // layer using any part of the current layer's alpha, then we can
+ // conservatively say that the canvas will not be transparent.
+ SkXfermode::Mode xferMode = SkXfermode::kSrc_Mode;
+ if (paint)
+ SkXfermode::AsMode(paint->getXfermode(), &xferMode);
+ if (xferMode != SkXfermode::kSrc_Mode)
+ (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(true);
+
+ ++savedLayerStackSize_;
+
// Actually saving a layer here could cause a new bitmap to be created
// and real rendering to occur.
- int count = SkCanvas::save(flags);
+ int count = INHERITED::save(flags);
if (bounds) {
INHERITED::clipRectBounds(bounds, flags, NULL);
}
return count;
}
+void AnalysisCanvas::restore() {
+ INHERITED::restore();
+
+ if (--savedLayerStackSize_ == 0) {
+ (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(false);
+ (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(false);
+ }
+}
+
} // namespace skia
« cc/tile_manager.cc ('K') | « skia/ext/analysis_canvas.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698