summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-08 22:45:18 +0000
committeralokp@chromium.org <alokp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-08 22:45:18 +0000
commit58838bf7106c6f2a0c75af275e7b60bd1faea3d6 (patch)
tree1fc2954fb35830073ffcee016d50d3d22fe29624
parent1389a03f1ac25bf7e80fb88cdbff5e48abd875a1 (diff)
downloadchromium_src-58838bf7106c6f2a0c75af275e7b60bd1faea3d6.zip
chromium_src-58838bf7106c6f2a0c75af275e7b60bd1faea3d6.tar.gz
chromium_src-58838bf7106c6f2a0c75af275e7b60bd1faea3d6.tar.bz2
Smart layer invalidation for LCD text.
When LCD text needs to be disabled for a layer, we can invalidate just the tiles containing text. This only works with impl-side painting where it is very cheap to mark tiles that have text. BUG=181245 Review URL: https://chromiumcodereview.appspot.com/13726013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192936 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/layers/picture_layer_impl.cc5
-rw-r--r--cc/resources/picture_layer_tiling.cc13
-rw-r--r--cc/resources/picture_layer_tiling.h1
-rw-r--r--cc/resources/picture_layer_tiling_set.cc5
-rw-r--r--cc/resources/picture_layer_tiling_set.h1
-rw-r--r--cc/resources/picture_pile_impl.cc2
-rw-r--r--cc/resources/picture_pile_impl.h1
-rw-r--r--cc/resources/tile.h3
-rw-r--r--skia/ext/analysis_canvas.cc19
-rw-r--r--skia/ext/analysis_canvas.h3
-rw-r--r--skia/ext/analysis_canvas_unittest.cc125
11 files changed, 172 insertions, 6 deletions
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index a2c951c..728c8f7 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -854,10 +854,7 @@ void PictureLayerImpl::UpdateLCDTextStatus() {
pending_layer->is_using_lcd_text_ = is_using_lcd_text_;
pending_layer->pile_ = PicturePileImpl::CreateFromOther(pending_layer->pile_,
is_using_lcd_text_);
-
- // TODO(enne): if we tracked text regions, we could just invalidate those
- // directly rather than tossing away every tile.
- pending_layer->tilings_->Invalidate(gfx::Rect(bounds()));
+ pending_layer->tilings_->InvalidateTilesWithText();
}
void PictureLayerImpl::ResetRasterScale() {
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index c3a2ffe..62350fc 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -156,6 +156,19 @@ void PictureLayerTiling::Invalidate(const Region& layer_invalidation) {
CreateTile(new_tiles[i].first, new_tiles[i].second);
}
+void PictureLayerTiling::InvalidateTilesWithText() {
+ std::vector<TileMapKey> new_tiles;
+ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
+ if (it->second->has_text())
+ new_tiles.push_back(it->first);
+ }
+
+ for (size_t i = 0; i < new_tiles.size(); ++i) {
+ tiles_.erase(new_tiles[i]);
+ CreateTile(new_tiles[i].first, new_tiles[i].second);
+ }
+}
+
void PictureLayerTiling::CreateTilesFromLayerRect(gfx::Rect layer_rect) {
gfx::Rect content_rect =
gfx::ToEnclosingRect(ScaleRect(layer_rect, contents_scale_));
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index 67e757a..5a83e40 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -50,6 +50,7 @@ class CC_EXPORT PictureLayerTiling {
gfx::Size layer_bounds() const { return layer_bounds_; }
void SetLayerBounds(gfx::Size layer_bounds);
void Invalidate(const Region& layer_invalidation);
+ void InvalidateTilesWithText();
// Add any tiles that intersect with |layer_rect|. If any tiles already
// exist, then this leaves them as-is.
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index b5460b9..1b26e56 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -81,6 +81,11 @@ void PictureLayerTilingSet::Invalidate(const Region& layer_invalidation) {
tilings_[i]->Invalidate(layer_invalidation);
}
+void PictureLayerTilingSet::InvalidateTilesWithText() {
+ for (size_t i = 0; i < tilings_.size(); ++i)
+ tilings_[i]->InvalidateTilesWithText();
+}
+
PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
tilings_.push_back(PictureLayerTiling::Create(contents_scale));
PictureLayerTiling* appended = tilings_.back();
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index c9d32de..f88d1ef1 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -30,6 +30,7 @@ class CC_EXPORT PictureLayerTilingSet {
gfx::Size LayerBounds() const;
void Invalidate(const Region& layer_invalidation);
+ void InvalidateTilesWithText();
PictureLayerTiling* AddTiling(float contents_scale);
size_t num_tilings() const { return tilings_.size(); }
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc
index 6e71cad..397d64c 100644
--- a/cc/resources/picture_pile_impl.cc
+++ b/cc/resources/picture_pile_impl.cc
@@ -262,12 +262,14 @@ void PicturePileImpl::AnalyzeInRect(const gfx::Rect& content_rect,
analysis->is_transparent = canvas.isTransparent();
analysis->is_solid_color = canvas.getColorIfSolid(&analysis->solid_color);
analysis->is_cheap_to_raster = canvas.isCheap();
+ analysis->has_text = canvas.hasText();
canvas.consumeLazyPixelRefs(&analysis->lazy_pixel_refs);
}
PicturePileImpl::Analysis::Analysis()
: is_solid_color(false),
is_transparent(false),
+ has_text(false),
is_cheap_to_raster(false) {
}
diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h
index 34364bd..9b49ed9 100644
--- a/cc/resources/picture_pile_impl.h
+++ b/cc/resources/picture_pile_impl.h
@@ -50,6 +50,7 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase {
bool is_solid_color;
bool is_transparent;
+ bool has_text;
bool is_cheap_to_raster;
SkColor solid_color;
diff --git a/cc/resources/tile.h b/cc/resources/tile.h
index d519851..608aef7 100644
--- a/cc/resources/tile.h
+++ b/cc/resources/tile.h
@@ -55,6 +55,9 @@ class CC_EXPORT Tile : public base::RefCounted<Tile> {
}
const gfx::Rect& opaque_rect() const { return opaque_rect_; }
+ bool has_text() const {
+ return managed_state_.picture_pile_analysis.has_text;
+ }
float contents_scale() const { return contents_scale_; }
gfx::Rect content_rect() const { return content_rect_; }
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc
index 93580b0..0af76f2 100644
--- a/skia/ext/analysis_canvas.cc
+++ b/skia/ext/analysis_canvas.cc
@@ -96,8 +96,8 @@ AnalysisDevice::AnalysisDevice(const SkBitmap& bm)
, isForcedNotSolid_(false)
, isForcedNotTransparent_(false)
, isSolidColor_(false)
- , isTransparent_(false) {
-
+ , isTransparent_(false)
+ , hasText_(false) {
}
AnalysisDevice::~AnalysisDevice() {
@@ -118,6 +118,10 @@ bool AnalysisDevice::isTransparent() const {
return isTransparent_;
}
+bool AnalysisDevice::hasText() const {
+ return hasText_;
+}
+
void AnalysisDevice::setForceNotSolid(bool flag) {
isForcedNotSolid_ = flag;
if (isForcedNotSolid_)
@@ -181,6 +185,7 @@ void AnalysisDevice::clear(SkColor color) {
estimatedCost_ += kUnknownExpensiveCost;
isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0);
+ hasText_ = false;
if (!isForcedNotSolid_ && SkColorGetA(color) == 255) {
isSolidColor_ = true;
@@ -246,6 +251,7 @@ void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
!isForcedNotTransparent_ &&
xferMode == SkXfermode::kClear_Mode) {
isTransparent_ = true;
+ hasText_ = false;
}
else if (paint.getAlpha() != 0 ||
xferMode != SkXfermode::kSrc_Mode) {
@@ -262,6 +268,7 @@ void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
doesCoverCanvas) {
isSolidColor_ = true;
color_ = paint.getColor();
+ hasText_ = false;
}
else {
isSolidColor_ = false;
@@ -346,6 +353,7 @@ void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len,
}
isSolidColor_ = false;
isTransparent_ = false;
+ hasText_ = true;
}
void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text,
@@ -361,6 +369,7 @@ void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text,
}
isSolidColor_ = false;
isTransparent_ = false;
+ hasText_ = true;
}
void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text,
@@ -374,6 +383,7 @@ void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text,
}
isSolidColor_ = false;
isTransparent_ = false;
+ hasText_ = true;
}
#ifdef SK_BUILD_FOR_ANDROID
@@ -388,6 +398,7 @@ void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text,
}
isSolidColor_ = false;
isTransparent_ = false;
+ hasText_ = true;
}
#endif
@@ -441,6 +452,10 @@ bool AnalysisCanvas::isTransparent() const {
return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent();
}
+bool AnalysisCanvas::hasText() const {
+ return (static_cast<AnalysisDevice*>(getDevice()))->hasText();
+}
+
int AnalysisCanvas::getEstimatedCost() const {
return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost();
}
diff --git a/skia/ext/analysis_canvas.h b/skia/ext/analysis_canvas.h
index 3c2daaf..4ebf793 100644
--- a/skia/ext/analysis_canvas.h
+++ b/skia/ext/analysis_canvas.h
@@ -35,6 +35,7 @@ class SK_API AnalysisCanvas : public SkCanvas {
bool isCheap() const;
bool getColorIfSolid(SkColor* color) const;
bool isTransparent() const;
+ bool hasText() const;
void consumeLazyPixelRefs(LazyPixelRefList* pixelRefs);
// Returns the estimated cost of drawing, in arbitrary units.
@@ -76,6 +77,7 @@ class SK_API AnalysisDevice : public SkDevice {
int getEstimatedCost() const;
bool getColorIfSolid(SkColor* color) const;
bool isTransparent() const;
+ bool hasText() const;
void consumeLazyPixelRefs(LazyPixelRefList* pixelRefs);
void setForceNotSolid(bool flag);
@@ -144,6 +146,7 @@ class SK_API AnalysisDevice : public SkDevice {
bool isSolidColor_;
SkColor color_;
bool isTransparent_;
+ bool hasText_;
IdSet existingPixelRefIDs_;
LazyPixelRefList lazyPixelRefs_;
};
diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc
index 46c9645..a8a9d0d 100644
--- a/skia/ext/analysis_canvas_unittest.cc
+++ b/skia/ext/analysis_canvas_unittest.cc
@@ -454,4 +454,129 @@ TEST(AnalysisCanvasTest, PixelRefsFromPaint) {
}
}
+TEST(AnalysisCanvasTest, HasText) {
+ int width = 200;
+ int height = 100;
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kNo_Config, width, height);
+
+ const char* text = "A";
+ size_t byteLength = 1;
+
+ SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25));
+ SkPath path;
+ path.moveTo(point);
+ path.lineTo(SkIntToScalar(75), SkIntToScalar(75));
+
+ SkPaint paint;
+ paint.setColor(SK_ColorGRAY);
+ paint.setTextSize(SkIntToScalar(10));
+
+ {
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ // Test after initialization.
+ EXPECT_FALSE(canvas.hasText());
+ // Test drawing anything other than text.
+ canvas.drawRect(SkRect::MakeWH(width/2, height), paint);
+ EXPECT_FALSE(canvas.hasText());
+ }
+ {
+ // Test SkCanvas::drawText.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Test SkCanvas::drawPosText.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawPosText(text, byteLength, &point, paint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Test SkCanvas::drawPosTextH.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawPosTextH(text, byteLength, &point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Test SkCanvas::drawTextOnPathHV.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawTextOnPathHV(text, byteLength, path, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Test SkCanvas::drawTextOnPath.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawTextOnPath(text, byteLength, path, NULL, paint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Text under opaque rect.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ canvas.drawRect(SkRect::MakeWH(width, height), paint);
+ EXPECT_FALSE(canvas.hasText());
+ }
+ {
+ // Text under translucent rect.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ SkPaint translucentPaint;
+ translucentPaint.setColor(0x88FFFFFF);
+ canvas.drawRect(SkRect::MakeWH(width, height), translucentPaint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Text under rect in clear mode.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ SkPaint clearModePaint;
+ clearModePaint.setXfermodeMode(SkXfermode::kClear_Mode);
+ canvas.drawRect(SkRect::MakeWH(width, height), clearModePaint);
+ EXPECT_FALSE(canvas.hasText());
+ }
+ {
+ // Clear.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ canvas.clear(SK_ColorGRAY);
+ EXPECT_FALSE(canvas.hasText());
+ }
+ {
+ // Text inside clip region.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.clipRect(SkRect::MakeWH(100, 100));
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ EXPECT_TRUE(canvas.hasText());
+ }
+ {
+ // Text outside clip region.
+ skia::AnalysisDevice device(bitmap);
+ skia::AnalysisCanvas canvas(&device);
+ canvas.clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
+ canvas.drawText(text, byteLength, point.fX, point.fY, paint);
+ // Analysis device does not do any clipping.
+ // So even when text is outside the clip region,
+ // it is marked as having the text.
+ // TODO(alokp): We may be able to do some trivial rejection.
+ EXPECT_TRUE(canvas.hasText());
+ }
+}
+
} // namespace skia