picture_pile.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/resources/picture_pile.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/region.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/picture_pile_impl.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum number of pictures that can overlap before we collapse them into 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a larger one. 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kMaxOverlapping = 2; 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Maximum percentage area of the base picture another picture in the picture 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// list can be. If higher, we destroy the list and recreate from scratch. 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kResetThreshold = 0.7f; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Layout pixel buffer around the visible layer rect to record. Any base 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// picture that intersects the visible layer rect expanded by this distance 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// will be recorded. 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kPixelDistanceToRecord = 8000; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PicturePile::PicturePile() { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PicturePile::~PicturePile() { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PicturePile::Update( 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ContentLayerClient* painter, 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor background_color, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Region& invalidation, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect visible_layer_rect, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RenderingStats* stats) { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background_color_ = background_color; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect interest_rect = visible_layer_rect; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) interest_rect.Inset( 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -kPixelDistanceToRecord, 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -kPixelDistanceToRecord, 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -kPixelDistanceToRecord, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -kPixelDistanceToRecord); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (Region::Iterator i(invalidation); i.has_rect(); i.next()) { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Inflate all recordings from invalidations with a margin so that when 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // scaled down to at least min_contents_scale, any final pixel touched by an 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // invalidation can be fully rasterized by this picture. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect inflated_invalidation = i.rect(); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inflated_invalidation.Inset( 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels(), 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels(), 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels(), 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels()); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Split this inflated invalidation across tile boundaries and apply it 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to all tiles that it touches. 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (TilingData::Iterator iter(&tiling_, inflated_invalidation); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter; ++iter) { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect tile = 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tiling_.TileBoundsWithBorder(iter.index_x(), iter.index_y()); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!tile.Intersects(interest_rect)) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This invalidation touches a tile outside the interest rect, so 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // just remove the entire picture list. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_list_map_.erase(iter.index()); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect tile_invalidation = 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::IntersectRects(inflated_invalidation, tile); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tile_invalidation.IsEmpty()) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PictureListMap::iterator find = picture_list_map_.find(iter.index()); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (find == picture_list_map_.end()) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PictureList& pic_list = find->second; 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Leave empty pic_lists empty in case there are multiple invalidations. 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!pic_list.empty()) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InvalidateRect(pic_list, tile_invalidation); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Walk through all pictures in the rect of interest and record. 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (TilingData::Iterator iter(&tiling_, interest_rect); iter; ++iter) { 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a picture in this list if it doesn't exist. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PictureList& pic_list = picture_list_map_[iter.index()]; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pic_list.empty()) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Inflate the base picture with a margin, similar to invalidations, so 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that when scaled down to at least min_contents_scale, the enclosed 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // rect still includes content all the way to the edge of the layer. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect tile = tiling_.TileBounds(iter.index_x(), iter.index_y()); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tile.Inset( 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels(), 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels(), 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels(), 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -buffer_pixels()); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<Picture> base_picture = Picture::Create(tile); 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pic_list.push_back(base_picture); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (PictureList::iterator pic = pic_list.begin(); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pic != pic_list.end(); ++pic) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!(*pic)->HasRecording()) { 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (*pic)->Record(painter, tile_grid_info_, stats); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (*pic)->GatherPixelRefs(tile_grid_info_, stats); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*pic)->CloneForDrawing(num_raster_threads_); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateRecordedRegion(); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FullyContainedPredicate { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) {} 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool operator()(const scoped_refptr<Picture>& picture) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return layer_rect_.Contains(picture->LayerRect()); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect layer_rect_; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PicturePile::InvalidateRect( 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PictureList& picture_list, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect invalidation) { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!picture_list.empty()); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<PictureList::iterator> overlaps; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (PictureList::iterator i = picture_list.begin(); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != picture_list.end(); ++i) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording()) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((*i)->LayerRect().Intersects(invalidation) && i != picture_list.begin()) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overlaps.push_back(i); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect picture_rect = invalidation; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (overlaps.size() >= kMaxOverlapping) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t j = 0; j < overlaps.size(); j++) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_rect.Union((*overlaps[j])->LayerRect()); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Picture* base_picture = picture_list.front(); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max_pixels = kResetThreshold * base_picture->LayerRect().size().GetArea(); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (picture_rect.size().GetArea() > max_pixels) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This picture list will be entirely recreated, so clear it. 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_list.clear(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FullyContainedPredicate pred(picture_rect); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_list.erase(std::remove_if(picture_list.begin(), 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_list.end(), 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pred), 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_list.end()); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) picture_list.push_back(Picture::Create(picture_rect)); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cc 162