picture_pile_base.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
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 <vector>
9
10#include "base/logging.h"
11#include "base/values.h"
12#include "cc/base/math_util.h"
13#include "cc/debug/traced_value.h"
14#include "third_party/skia/include/core/SkColor.h"
15#include "ui/gfx/rect_conversions.h"
16
17namespace {
18// Dimensions of the tiles in this picture pile as well as the dimensions of
19// the base picture in each tile.
20const int kBasePictureSize = 3000;
21const int kTileGridBorderPixels = 1;
22}
23
24namespace cc {
25
26PicturePileBase::PicturePileBase()
27    : min_contents_scale_(0),
28      background_color_(SkColorSetARGBInline(0, 0, 0, 0)),
29      contents_opaque_(false),
30      slow_down_raster_scale_factor_for_debug_(0),
31      show_debug_picture_borders_(false),
32      num_raster_threads_(0) {
33  tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize));
34  tile_grid_info_.fTileInterval.setEmpty();
35  tile_grid_info_.fMargin.setEmpty();
36  tile_grid_info_.fOffset.setZero();
37}
38
39PicturePileBase::PicturePileBase(const PicturePileBase* other)
40    : picture_list_map_(other->picture_list_map_),
41      tiling_(other->tiling_),
42      recorded_region_(other->recorded_region_),
43      min_contents_scale_(other->min_contents_scale_),
44      tile_grid_info_(other->tile_grid_info_),
45      background_color_(other->background_color_),
46      contents_opaque_(other->contents_opaque_),
47      slow_down_raster_scale_factor_for_debug_(
48          other->slow_down_raster_scale_factor_for_debug_),
49      show_debug_picture_borders_(other->show_debug_picture_borders_),
50      num_raster_threads_(other->num_raster_threads_) {
51}
52
53PicturePileBase::PicturePileBase(
54    const PicturePileBase* other, unsigned thread_index)
55    : tiling_(other->tiling_),
56      recorded_region_(other->recorded_region_),
57      min_contents_scale_(other->min_contents_scale_),
58      tile_grid_info_(other->tile_grid_info_),
59      background_color_(other->background_color_),
60      contents_opaque_(other->contents_opaque_),
61      slow_down_raster_scale_factor_for_debug_(
62          other->slow_down_raster_scale_factor_for_debug_),
63      show_debug_picture_borders_(other->show_debug_picture_borders_),
64      num_raster_threads_(other->num_raster_threads_) {
65  const PictureListMap& other_pic_list_map = other->picture_list_map_;
66  for (PictureListMap::const_iterator map_iter = other_pic_list_map.begin();
67       map_iter != other_pic_list_map.end(); ++map_iter) {
68    PictureList& pic_list = picture_list_map_[map_iter->first];
69    const PictureList& other_pic_list = map_iter->second;
70    for (PictureList::const_iterator pic_iter = other_pic_list.begin();
71         pic_iter != other_pic_list.end(); ++pic_iter) {
72      pic_list.push_back(
73          (*pic_iter)->GetCloneForDrawingOnThread(thread_index));
74    }
75  }
76}
77
78PicturePileBase::~PicturePileBase() {
79}
80
81void PicturePileBase::Resize(gfx::Size new_size) {
82  if (size() == new_size)
83    return;
84
85  gfx::Size old_size = size();
86  tiling_.SetTotalSize(new_size);
87
88  // Find all tiles that contain any pixels outside the new size.
89  std::vector<PictureListMapKey> to_erase;
90  int min_toss_x = tiling_.FirstBorderTileXIndexFromSrcCoord(
91      std::min(old_size.width(), new_size.width()));
92  int min_toss_y = tiling_.FirstBorderTileYIndexFromSrcCoord(
93      std::min(old_size.height(), new_size.height()));
94  for (PictureListMap::iterator iter = picture_list_map_.begin();
95       iter != picture_list_map_.end(); ++iter) {
96    if (iter->first.first < min_toss_x && iter->first.second < min_toss_y)
97      continue;
98    to_erase.push_back(iter->first);
99  }
100
101  for (size_t i = 0; i < to_erase.size(); ++i)
102    picture_list_map_.erase(to_erase[i]);
103}
104
105void PicturePileBase::SetMinContentsScale(float min_contents_scale) {
106  DCHECK(min_contents_scale);
107  if (min_contents_scale_ == min_contents_scale)
108    return;
109
110  // Picture contents are played back scaled. When the final contents scale is
111  // less than 1 (i.e. low res), then multiple recorded pixels will be used
112  // to raster one final pixel.  To avoid splitting a final pixel across
113  // pictures (which would result in incorrect rasterization due to blending), a
114  // buffer margin is added so that any picture can be snapped to integral
115  // final pixels.
116  //
117  // For example, if a 1/4 contents scale is used, then that would be 3 buffer
118  // pixels, since that's the minimum number of pixels to add so that resulting
119  // content can be snapped to a four pixel aligned grid.
120  int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1);
121  buffer_pixels = std::max(0, buffer_pixels);
122  SetBufferPixels(buffer_pixels);
123  min_contents_scale_ = min_contents_scale;
124}
125
126void PicturePileBase::SetTileGridSize(gfx::Size tile_grid_size) {
127  tile_grid_info_.fTileInterval.set(
128      tile_grid_size.width() - 2 * kTileGridBorderPixels,
129      tile_grid_size.height() - 2 * kTileGridBorderPixels);
130  DCHECK_GT(tile_grid_info_.fTileInterval.width(), 0);
131  DCHECK_GT(tile_grid_info_.fTileInterval.height(), 0);
132  tile_grid_info_.fMargin.set(kTileGridBorderPixels,
133      kTileGridBorderPixels);
134  // Offset the tile grid coordinate space to take into account the fact
135  // that the top-most and left-most tiles do not have top and left borders
136  // respectively.
137  tile_grid_info_.fOffset.set(-kTileGridBorderPixels,
138      -kTileGridBorderPixels);
139}
140
141void PicturePileBase::SetBufferPixels(int new_buffer_pixels) {
142  if (new_buffer_pixels == buffer_pixels())
143    return;
144
145  Clear();
146  tiling_.SetBorderTexels(new_buffer_pixels);
147}
148
149void PicturePileBase::Clear() {
150  picture_list_map_.clear();
151}
152
153void PicturePileBase::UpdateRecordedRegion() {
154  recorded_region_.Clear();
155  for (PictureListMap::iterator it = picture_list_map_.begin();
156       it != picture_list_map_.end(); ++it) {
157    const PictureListMapKey& key = it->first;
158    recorded_region_.Union(tile_bounds(key.first, key.second));
159  }
160}
161
162bool PicturePileBase::HasRecordingAt(int x, int y) {
163  PictureListMap::iterator found =
164      picture_list_map_.find(PictureListMapKey(x, y));
165  if (found == picture_list_map_.end())
166    return false;
167  DCHECK(!found->second.empty());
168  return true;
169}
170
171bool PicturePileBase::CanRaster(float contents_scale, gfx::Rect content_rect) {
172  if (tiling_.total_size().IsEmpty())
173    return false;
174  gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
175      content_rect, 1.f / contents_scale);
176  layer_rect.Intersect(gfx::Rect(tiling_.total_size()));
177  return recorded_region_.Contains(layer_rect);
178}
179
180scoped_ptr<base::Value> PicturePileBase::AsValue() const {
181  scoped_ptr<base::ListValue> pictures(new base::ListValue());
182  gfx::Rect layer_rect(tiling_.total_size());
183  for (TilingData::Iterator tile_iter(&tiling_, layer_rect);
184       tile_iter; ++tile_iter) {
185    PictureListMap::const_iterator map_iter =
186        picture_list_map_.find(tile_iter.index());
187    if (map_iter == picture_list_map_.end())
188      continue;
189    const PictureList& pic_list= map_iter->second;
190    if (pic_list.empty())
191      continue;
192    for (PictureList::const_reverse_iterator i = pic_list.rbegin();
193         i != pic_list.rend(); ++i) {
194      Picture* picture = (*i).get();
195      pictures->Append(TracedValue::CreateIDRef(picture).release());
196    }
197  }
198  return pictures.PassAs<base::Value>();
199}
200
201}  // namespace cc
202