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