summaryrefslogtreecommitdiffstats
path: root/cc/picture_pile.cc
blob: fcf746a01b3f3d9af8a9adc5a63f95db292aedd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>

#include "cc/picture_pile.h"
#include "cc/picture_pile_impl.h"
#include "cc/region.h"

namespace {
// Maximum number of pictures that can overlap before we collapse them into
// a larger one.
const int kMaxOverlapping = 2;
// Maximum percentage area of the base picture another picture in the pile
// can be.  If higher, we destroy the pile and recreate from scratch.
const float kResetThreshold = 0.7f;
}

namespace cc {

PicturePile::PicturePile() {
}

void PicturePile::Update(
    ContentLayerClient* painter,
    const Region& invalidation,
    RenderingStats& stats) {
  if (pile_.empty()) {
    ResetPile(painter, stats);
    return;
  }

  for (Region::Iterator i(invalidation); i.has_rect(); i.next())
    InvalidateRect(i.rect());

  for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) {
    if (!(*i)->HasRecording())
      (*i)->Record(painter, stats);
  }
}

class FullyContainedPredicate {
public:
  FullyContainedPredicate(gfx::Rect rect) : layer_rect_(rect) { }
  bool operator()(const scoped_refptr<Picture>& picture) {
    return layer_rect_.Contains(picture->LayerRect());
  }
  gfx::Rect layer_rect_;
};

void PicturePile::InvalidateRect(gfx::Rect invalidation) {
  if (invalidation.IsEmpty())
    return;

  // Inflate all recordings from invalidations with a margin so that when
  // scaled down to at least min_contents_scale, any final pixel touched by an
  // invalidation can be fully rasterized by this picture.
  invalidation.Inset(
      -buffer_pixels_,
      -buffer_pixels_,
      -buffer_pixels_,
      -buffer_pixels_);
  invalidation.Intersect(gfx::Rect(size_));

  std::vector<Pile::iterator> overlaps;
  for (Pile::iterator i = pile_.begin(); i != pile_.end(); ++i) {
    if ((*i)->LayerRect().Contains(invalidation) && !(*i)->HasRecording())
      return;
    if ((*i)->LayerRect().Intersects(invalidation) && i != pile_.begin())
      overlaps.push_back(i);
  }

  gfx::Rect picture_rect = invalidation;
  if (overlaps.size() >= kMaxOverlapping) {
    for (size_t j = 0; j < overlaps.size(); j++)
      picture_rect = gfx::UnionRects(picture_rect, (*overlaps[j])->LayerRect());
  }
  if (picture_rect.size().GetArea() / static_cast<float>(size_.GetArea()) >
      kResetThreshold)
    picture_rect = gfx::Rect(size_);

  FullyContainedPredicate pred(picture_rect);
  pile_.erase(std::remove_if(pile_.begin(), pile_.end(), pred), pile_.end());

  pile_.push_back(Picture::Create(picture_rect));
}


void PicturePile::ResetPile(ContentLayerClient* painter,
                            RenderingStats& stats) {
  pile_.clear();

  scoped_refptr<Picture> base_picture = Picture::Create(gfx::Rect(size_));
  base_picture->Record(painter, stats);
  pile_.push_back(base_picture);
}

void PicturePile::PushPropertiesTo(PicturePileImpl* other) {
  PicturePileBase::PushPropertiesTo(other);

  // Remove all old clones.
  other->clones_.clear();
}

}  // namespace cc