146c886d4780de0efc143c79a1eda79f7438d4cc
[platform/framework/web/crosswalk.git] / src / cc / resources / picture_pile_base.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/resources/picture_pile_base.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <vector>
10
11 #include "base/debug/trace_event_argument.h"
12 #include "base/logging.h"
13 #include "base/values.h"
14 #include "cc/base/math_util.h"
15 #include "cc/debug/traced_value.h"
16 #include "third_party/skia/include/core/SkColor.h"
17 #include "ui/gfx/rect_conversions.h"
18
19 namespace {
20 // Dimensions of the tiles in this picture pile as well as the dimensions of
21 // the base picture in each tile.
22 const int kBasePictureSize = 512;
23 const int kTileGridBorderPixels = 1;
24 #ifdef NDEBUG
25 const bool kDefaultClearCanvasSetting = false;
26 #else
27 const bool kDefaultClearCanvasSetting = true;
28 #endif
29
30 // Invalidation frequency settings. kInvalidationFrequencyThreshold is a value
31 // between 0 and 1 meaning invalidation frequency between 0% and 100% that
32 // indicates when to stop invalidating offscreen regions.
33 // kFrequentInvalidationDistanceThreshold defines what it means to be
34 // "offscreen" in terms of distance to visible in css pixels.
35 const float kInvalidationFrequencyThreshold = 0.75f;
36 const int kFrequentInvalidationDistanceThreshold = 512;
37
38 }  // namespace
39
40 namespace cc {
41
42 PicturePileBase::PicturePileBase()
43     : min_contents_scale_(0),
44       background_color_(SkColorSetARGBInline(0, 0, 0, 0)),
45       slow_down_raster_scale_factor_for_debug_(0),
46       contents_opaque_(false),
47       contents_fill_bounds_completely_(false),
48       show_debug_picture_borders_(false),
49       clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
50       has_any_recordings_(false) {
51   tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize));
52   tile_grid_info_.fTileInterval.setEmpty();
53   tile_grid_info_.fMargin.setEmpty();
54   tile_grid_info_.fOffset.setZero();
55 }
56
57 PicturePileBase::PicturePileBase(const PicturePileBase* other)
58     : picture_map_(other->picture_map_),
59       tiling_(other->tiling_),
60       recorded_viewport_(other->recorded_viewport_),
61       min_contents_scale_(other->min_contents_scale_),
62       tile_grid_info_(other->tile_grid_info_),
63       background_color_(other->background_color_),
64       slow_down_raster_scale_factor_for_debug_(
65           other->slow_down_raster_scale_factor_for_debug_),
66       contents_opaque_(other->contents_opaque_),
67       contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
68       show_debug_picture_borders_(other->show_debug_picture_borders_),
69       clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
70       has_any_recordings_(other->has_any_recordings_) {}
71
72 PicturePileBase::PicturePileBase(const PicturePileBase* other,
73                                  unsigned thread_index)
74     : tiling_(other->tiling_),
75       recorded_viewport_(other->recorded_viewport_),
76       min_contents_scale_(other->min_contents_scale_),
77       tile_grid_info_(other->tile_grid_info_),
78       background_color_(other->background_color_),
79       slow_down_raster_scale_factor_for_debug_(
80           other->slow_down_raster_scale_factor_for_debug_),
81       contents_opaque_(other->contents_opaque_),
82       contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
83       show_debug_picture_borders_(other->show_debug_picture_borders_),
84       clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
85       has_any_recordings_(other->has_any_recordings_) {
86   for (PictureMap::const_iterator it = other->picture_map_.begin();
87        it != other->picture_map_.end();
88        ++it) {
89     picture_map_[it->first] = it->second.CloneForThread(thread_index);
90   }
91 }
92
93 PicturePileBase::~PicturePileBase() {
94 }
95
96 void PicturePileBase::SetMinContentsScale(float min_contents_scale) {
97   DCHECK(min_contents_scale);
98   if (min_contents_scale_ == min_contents_scale)
99     return;
100
101   // Picture contents are played back scaled. When the final contents scale is
102   // less than 1 (i.e. low res), then multiple recorded pixels will be used
103   // to raster one final pixel.  To avoid splitting a final pixel across
104   // pictures (which would result in incorrect rasterization due to blending), a
105   // buffer margin is added so that any picture can be snapped to integral
106   // final pixels.
107   //
108   // For example, if a 1/4 contents scale is used, then that would be 3 buffer
109   // pixels, since that's the minimum number of pixels to add so that resulting
110   // content can be snapped to a four pixel aligned grid.
111   int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1);
112   buffer_pixels = std::max(0, buffer_pixels);
113   SetBufferPixels(buffer_pixels);
114   min_contents_scale_ = min_contents_scale;
115 }
116
117 // static
118 void PicturePileBase::ComputeTileGridInfo(
119     const gfx::Size& tile_grid_size,
120     SkTileGridFactory::TileGridInfo* info) {
121   DCHECK(info);
122   info->fTileInterval.set(tile_grid_size.width() - 2 * kTileGridBorderPixels,
123                           tile_grid_size.height() - 2 * kTileGridBorderPixels);
124   DCHECK_GT(info->fTileInterval.width(), 0);
125   DCHECK_GT(info->fTileInterval.height(), 0);
126   info->fMargin.set(kTileGridBorderPixels, kTileGridBorderPixels);
127   // Offset the tile grid coordinate space to take into account the fact
128   // that the top-most and left-most tiles do not have top and left borders
129   // respectively.
130   info->fOffset.set(-kTileGridBorderPixels, -kTileGridBorderPixels);
131 }
132
133 void PicturePileBase::SetTileGridSize(const gfx::Size& tile_grid_size) {
134   ComputeTileGridInfo(tile_grid_size, &tile_grid_info_);
135 }
136
137 void PicturePileBase::SetBufferPixels(int new_buffer_pixels) {
138   if (new_buffer_pixels == buffer_pixels())
139     return;
140
141   Clear();
142   tiling_.SetBorderTexels(new_buffer_pixels);
143 }
144
145 void PicturePileBase::Clear() {
146   picture_map_.clear();
147   recorded_viewport_ = gfx::Rect();
148 }
149
150 bool PicturePileBase::HasRecordingAt(int x, int y) {
151   PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y));
152   if (found == picture_map_.end())
153     return false;
154   return !!found->second.GetPicture();
155 }
156
157 bool PicturePileBase::CanRaster(float contents_scale,
158                                 const gfx::Rect& content_rect) {
159   if (tiling_.tiling_size().IsEmpty())
160     return false;
161   gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
162       content_rect, 1.f / contents_scale);
163   layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
164
165   // Common case inside of viewport to avoid the slower map lookups.
166   if (recorded_viewport_.Contains(layer_rect)) {
167     // Sanity check that there are no false positives in recorded_viewport_.
168     DCHECK(CanRasterSlowTileCheck(layer_rect));
169     return true;
170   }
171
172   return CanRasterSlowTileCheck(layer_rect);
173 }
174
175 bool PicturePileBase::CanRasterSlowTileCheck(
176     const gfx::Rect& layer_rect) const {
177   bool include_borders = false;
178   for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
179        tile_iter;
180        ++tile_iter) {
181     PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
182     if (map_iter == picture_map_.end())
183       return false;
184     if (!map_iter->second.GetPicture())
185       return false;
186   }
187   return true;
188 }
189
190 gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) {
191   gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
192   return PadRect(tile);
193 }
194
195 gfx::Rect PicturePileBase::PadRect(const gfx::Rect& rect) {
196   gfx::Rect padded_rect = rect;
197   padded_rect.Inset(
198       -buffer_pixels(), -buffer_pixels(), -buffer_pixels(), -buffer_pixels());
199   return padded_rect;
200 }
201
202 void PicturePileBase::AsValueInto(base::debug::TracedValue* pictures) const {
203   gfx::Rect tiling_rect(tiling_.tiling_size());
204   std::set<void*> appended_pictures;
205   bool include_borders = true;
206   for (TilingData::Iterator tile_iter(&tiling_, tiling_rect, include_borders);
207        tile_iter;
208        ++tile_iter) {
209     PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
210     if (map_iter == picture_map_.end())
211       continue;
212
213     Picture* picture = map_iter->second.GetPicture();
214     if (picture && (appended_pictures.count(picture) == 0)) {
215       appended_pictures.insert(picture);
216       TracedValue::AppendIDRef(picture, pictures);
217     }
218   }
219 }
220
221 PicturePileBase::PictureInfo::PictureInfo() : last_frame_number_(0) {}
222
223 PicturePileBase::PictureInfo::~PictureInfo() {}
224
225 void PicturePileBase::PictureInfo::AdvanceInvalidationHistory(
226     int frame_number) {
227   DCHECK_GE(frame_number, last_frame_number_);
228   if (frame_number == last_frame_number_)
229     return;
230
231   invalidation_history_ <<= (frame_number - last_frame_number_);
232   last_frame_number_ = frame_number;
233 }
234
235 bool PicturePileBase::PictureInfo::Invalidate(int frame_number) {
236   AdvanceInvalidationHistory(frame_number);
237   invalidation_history_.set(0);
238
239   bool did_invalidate = !!picture_;
240   picture_ = NULL;
241   return did_invalidate;
242 }
243
244 bool PicturePileBase::PictureInfo::NeedsRecording(int frame_number,
245                                                   int distance_to_visible) {
246   AdvanceInvalidationHistory(frame_number);
247
248   // We only need recording if we don't have a picture. Furthermore, we only
249   // need a recording if we're within frequent invalidation distance threshold
250   // or the invalidation is not frequent enough (below invalidation frequency
251   // threshold).
252   return !picture_ &&
253          ((distance_to_visible <= kFrequentInvalidationDistanceThreshold) ||
254           (GetInvalidationFrequency() < kInvalidationFrequencyThreshold));
255 }
256
257 void PicturePileBase::PictureInfo::SetPicture(scoped_refptr<Picture> picture) {
258   picture_ = picture;
259 }
260
261 Picture* PicturePileBase::PictureInfo::GetPicture() const {
262   return picture_.get();
263 }
264
265 PicturePileBase::PictureInfo PicturePileBase::PictureInfo::CloneForThread(
266     int thread_index) const {
267   PictureInfo info = *this;
268   if (picture_.get())
269     info.picture_ = picture_->GetCloneForDrawingOnThread(thread_index);
270   return info;
271 }
272
273 float PicturePileBase::PictureInfo::GetInvalidationFrequency() const {
274   return invalidation_history_.count() /
275          static_cast<float>(INVALIDATION_FRAMES_TRACKED);
276 }
277
278 }  // namespace cc