Index: cc/picture_pile_impl.cc |
diff --git a/cc/picture_pile_impl.cc b/cc/picture_pile_impl.cc |
index 4bb01a397dad325a0cfb138827b7fd0e70aea991..a4be4d46b7907c2c8c7d49991b00711dcfd0571f 100644 |
--- a/cc/picture_pile_impl.cc |
+++ b/cc/picture_pile_impl.cc |
@@ -7,6 +7,7 @@ |
#include "cc/picture_pile_impl.h" |
#include "cc/region.h" |
#include "cc/rendering_stats.h" |
+#include "skia/ext/analysis_canvas.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
#include "third_party/skia/include/core/SkSize.h" |
#include "ui/gfx/rect_conversions.h" |
@@ -188,28 +189,87 @@ skia::RefPtr<SkPicture> PicturePileImpl::GetFlattenedPicture() { |
return picture; |
} |
-bool PicturePileImpl::IsCheapInRect( |
- gfx::Rect content_rect, float contents_scale) const { |
+void PicturePileImpl::AnalyzeInRect(const gfx::Rect& content_rect, |
+ float contents_scale, |
+ Picture::Analysis* analysis) { |
+ DCHECK(analysis); |
+ |
+ TRACE_EVENT0("cc", "PicturePileImpl::AnalyzeInRect"); |
+ |
gfx::Rect layer_rect = gfx::ToEnclosingRect( |
gfx::ScaleRect(content_rect, 1.f / contents_scale)); |
+ SkBitmap emptyBitmap; |
+ emptyBitmap.setConfig(SkBitmap::kNo_Config, content_rect.width(), |
+ content_rect.height()); |
+ skia::AnalysisDevice device(emptyBitmap); |
+ skia::AnalysisCanvas canvas(&device); |
+ |
+ canvas.translate(-content_rect.x(), -content_rect.y()); |
+ canvas.clipRect(gfx::RectToSkRect(content_rect)); |
+ |
+ Region unclipped(content_rect); |
+ analysis->is_solid_color = false; |
+ analysis->is_transparent = false; |
+ analysis->is_cheap_to_raster = false; |
+ |
+ bool determined_if_transparent = false; |
+ bool is_transparent_guess = false; |
+ bool cheap = true; |
for (TilingData::Iterator tile_iter(&tiling_, layer_rect); |
tile_iter; ++tile_iter) { |
- PictureListMap::const_iterator map_iter = |
+ PictureListMap::iterator map_iter = |
picture_list_map_.find(tile_iter.index()); |
if (map_iter == picture_list_map_.end()) |
continue; |
+ PictureList& pic_list= map_iter->second; |
+ if (pic_list.empty()) |
+ continue; |
- const PictureList& pic_list = map_iter->second; |
- for (PictureList::const_iterator i = pic_list.begin(); |
- i != pic_list.end(); ++i) { |
- if (!(*i)->LayerRect().Intersects(layer_rect) || !(*i)->HasRecording()) |
+ for (PictureList::reverse_iterator i = pic_list.rbegin(); |
+ i != pic_list.rend(); ++i) { |
+ gfx::Rect content_clip = gfx::ToEnclosedRect( |
+ gfx::ScaleRect((*i)->LayerRect(), contents_scale)); |
+ if (!unclipped.Intersects(content_clip)) |
continue; |
- if (!(*i)->IsCheapInRect(layer_rect)) |
- return false; |
+ |
+ Picture::Analysis picture_analysis; |
+ (*i)->AnalyzeInRect(&canvas, |
+ content_clip, |
+ contents_scale, |
+ &picture_analysis); |
+ |
+ // Since the iteration happens bottom-up, take the solid information |
+ // from the last picture that is analyzed. |
+ analysis->is_solid_color = picture_analysis.is_solid_color; |
+ analysis->solid_color = picture_analysis.solid_color; |
+ |
+ // If the current picture is transparent, then the best we can do |
+ // is guess that the whole tile will be transparent (since that |
+ // might change in later iterations) |
+ if (picture_analysis.is_transparent) |
+ is_transparent_guess = true; |
+ else { |
+ analysis->is_transparent = false; |
+ determined_if_transparent = true; |
+ } |
+ |
+ // Cheap can turn into not cheap, but not cheap |
+ // can't be updated to be cheap |
+ if (cheap) |
+ cheap = picture_analysis.is_cheap_to_raster; |
+ |
+ // Don't allow pictures underneath to draw where this picture did. |
+ canvas.clipRect( |
+ gfx::RectToSkRect(content_clip), |
+ SkRegion::kDifference_Op); |
+ unclipped.Subtract(content_clip); |
} |
} |
- return true; |
+ |
+ if (!determined_if_transparent) |
+ analysis->is_transparent = is_transparent_guess; |
+ analysis->is_cheap_to_raster = cheap; |
} |
} // namespace cc |