| OLD | NEW |
| (Empty) |
| 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/debug/traced_value.h" | |
| 15 #include "third_party/skia/include/core/SkColor.h" | |
| 16 #include "ui/gfx/geometry/rect_conversions.h" | |
| 17 | |
| 18 namespace { | |
| 19 // Dimensions of the tiles in this picture pile as well as the dimensions of | |
| 20 // the base picture in each tile. | |
| 21 const int kBasePictureSize = 512; | |
| 22 const int kTileGridBorderPixels = 1; | |
| 23 #ifdef NDEBUG | |
| 24 const bool kDefaultClearCanvasSetting = false; | |
| 25 #else | |
| 26 const bool kDefaultClearCanvasSetting = true; | |
| 27 #endif | |
| 28 | |
| 29 // Invalidation frequency settings. kInvalidationFrequencyThreshold is a value | |
| 30 // between 0 and 1 meaning invalidation frequency between 0% and 100% that | |
| 31 // indicates when to stop invalidating offscreen regions. | |
| 32 // kFrequentInvalidationDistanceThreshold defines what it means to be | |
| 33 // "offscreen" in terms of distance to visible in css pixels. | |
| 34 const float kInvalidationFrequencyThreshold = 0.75f; | |
| 35 const int kFrequentInvalidationDistanceThreshold = 512; | |
| 36 | |
| 37 } // namespace | |
| 38 | |
| 39 namespace cc { | |
| 40 | |
| 41 PicturePileBase::PicturePileBase() | |
| 42 : min_contents_scale_(0), | |
| 43 background_color_(SkColorSetARGBInline(0, 0, 0, 0)), | |
| 44 slow_down_raster_scale_factor_for_debug_(0), | |
| 45 contents_opaque_(false), | |
| 46 contents_fill_bounds_completely_(false), | |
| 47 show_debug_picture_borders_(false), | |
| 48 clear_canvas_with_debug_color_(kDefaultClearCanvasSetting), | |
| 49 has_any_recordings_(false), | |
| 50 is_mask_(false), | |
| 51 is_solid_color_(false), | |
| 52 solid_color_(SK_ColorTRANSPARENT) { | |
| 53 tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize)); | |
| 54 tile_grid_info_.fTileInterval.setEmpty(); | |
| 55 tile_grid_info_.fMargin.setEmpty(); | |
| 56 tile_grid_info_.fOffset.setZero(); | |
| 57 } | |
| 58 | |
| 59 PicturePileBase::PicturePileBase(const PicturePileBase* other) | |
| 60 : picture_map_(other->picture_map_), | |
| 61 tiling_(other->tiling_), | |
| 62 recorded_viewport_(other->recorded_viewport_), | |
| 63 min_contents_scale_(other->min_contents_scale_), | |
| 64 tile_grid_info_(other->tile_grid_info_), | |
| 65 background_color_(other->background_color_), | |
| 66 slow_down_raster_scale_factor_for_debug_( | |
| 67 other->slow_down_raster_scale_factor_for_debug_), | |
| 68 contents_opaque_(other->contents_opaque_), | |
| 69 contents_fill_bounds_completely_(other->contents_fill_bounds_completely_), | |
| 70 show_debug_picture_borders_(other->show_debug_picture_borders_), | |
| 71 clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_), | |
| 72 has_any_recordings_(other->has_any_recordings_), | |
| 73 is_mask_(other->is_mask_), | |
| 74 is_solid_color_(other->is_solid_color_), | |
| 75 solid_color_(other->solid_color_) { | |
| 76 } | |
| 77 | |
| 78 PicturePileBase::~PicturePileBase() { | |
| 79 } | |
| 80 | |
| 81 void PicturePileBase::SetMinContentsScale(float min_contents_scale) { | |
| 82 DCHECK(min_contents_scale); | |
| 83 if (min_contents_scale_ == min_contents_scale) | |
| 84 return; | |
| 85 | |
| 86 // Picture contents are played back scaled. When the final contents scale is | |
| 87 // less than 1 (i.e. low res), then multiple recorded pixels will be used | |
| 88 // to raster one final pixel. To avoid splitting a final pixel across | |
| 89 // pictures (which would result in incorrect rasterization due to blending), a | |
| 90 // buffer margin is added so that any picture can be snapped to integral | |
| 91 // final pixels. | |
| 92 // | |
| 93 // For example, if a 1/4 contents scale is used, then that would be 3 buffer | |
| 94 // pixels, since that's the minimum number of pixels to add so that resulting | |
| 95 // content can be snapped to a four pixel aligned grid. | |
| 96 int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1); | |
| 97 buffer_pixels = std::max(0, buffer_pixels); | |
| 98 SetBufferPixels(buffer_pixels); | |
| 99 min_contents_scale_ = min_contents_scale; | |
| 100 } | |
| 101 | |
| 102 // static | |
| 103 void PicturePileBase::ComputeTileGridInfo( | |
| 104 const gfx::Size& tile_grid_size, | |
| 105 SkTileGridFactory::TileGridInfo* info) { | |
| 106 DCHECK(info); | |
| 107 info->fTileInterval.set(tile_grid_size.width() - 2 * kTileGridBorderPixels, | |
| 108 tile_grid_size.height() - 2 * kTileGridBorderPixels); | |
| 109 DCHECK_GT(info->fTileInterval.width(), 0); | |
| 110 DCHECK_GT(info->fTileInterval.height(), 0); | |
| 111 info->fMargin.set(kTileGridBorderPixels, kTileGridBorderPixels); | |
| 112 // Offset the tile grid coordinate space to take into account the fact | |
| 113 // that the top-most and left-most tiles do not have top and left borders | |
| 114 // respectively. | |
| 115 info->fOffset.set(-kTileGridBorderPixels, -kTileGridBorderPixels); | |
| 116 } | |
| 117 | |
| 118 void PicturePileBase::SetTileGridSize(const gfx::Size& tile_grid_size) { | |
| 119 ComputeTileGridInfo(tile_grid_size, &tile_grid_info_); | |
| 120 } | |
| 121 | |
| 122 void PicturePileBase::SetBufferPixels(int new_buffer_pixels) { | |
| 123 if (new_buffer_pixels == buffer_pixels()) | |
| 124 return; | |
| 125 | |
| 126 Clear(); | |
| 127 tiling_.SetBorderTexels(new_buffer_pixels); | |
| 128 } | |
| 129 | |
| 130 void PicturePileBase::Clear() { | |
| 131 picture_map_.clear(); | |
| 132 recorded_viewport_ = gfx::Rect(); | |
| 133 has_any_recordings_ = false; | |
| 134 is_solid_color_ = false; | |
| 135 } | |
| 136 | |
| 137 bool PicturePileBase::HasRecordingAt(int x, int y) { | |
| 138 PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y)); | |
| 139 if (found == picture_map_.end()) | |
| 140 return false; | |
| 141 return !!found->second.GetPicture(); | |
| 142 } | |
| 143 | |
| 144 gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) const { | |
| 145 gfx::Rect tile = tiling_.TileBounds(key.first, key.second); | |
| 146 return PadRect(tile); | |
| 147 } | |
| 148 | |
| 149 gfx::Rect PicturePileBase::PadRect(const gfx::Rect& rect) const { | |
| 150 gfx::Rect padded_rect = rect; | |
| 151 padded_rect.Inset( | |
| 152 -buffer_pixels(), -buffer_pixels(), -buffer_pixels(), -buffer_pixels()); | |
| 153 return padded_rect; | |
| 154 } | |
| 155 | |
| 156 PicturePileBase::PictureInfo::PictureInfo() : last_frame_number_(0) {} | |
| 157 | |
| 158 PicturePileBase::PictureInfo::~PictureInfo() {} | |
| 159 | |
| 160 void PicturePileBase::PictureInfo::AdvanceInvalidationHistory( | |
| 161 int frame_number) { | |
| 162 DCHECK_GE(frame_number, last_frame_number_); | |
| 163 if (frame_number == last_frame_number_) | |
| 164 return; | |
| 165 | |
| 166 invalidation_history_ <<= (frame_number - last_frame_number_); | |
| 167 last_frame_number_ = frame_number; | |
| 168 } | |
| 169 | |
| 170 bool PicturePileBase::PictureInfo::Invalidate(int frame_number) { | |
| 171 AdvanceInvalidationHistory(frame_number); | |
| 172 invalidation_history_.set(0); | |
| 173 | |
| 174 bool did_invalidate = !!picture_.get(); | |
| 175 picture_ = NULL; | |
| 176 return did_invalidate; | |
| 177 } | |
| 178 | |
| 179 bool PicturePileBase::PictureInfo::NeedsRecording(int frame_number, | |
| 180 int distance_to_visible) { | |
| 181 AdvanceInvalidationHistory(frame_number); | |
| 182 | |
| 183 // We only need recording if we don't have a picture. Furthermore, we only | |
| 184 // need a recording if we're within frequent invalidation distance threshold | |
| 185 // or the invalidation is not frequent enough (below invalidation frequency | |
| 186 // threshold). | |
| 187 return !picture_.get() && | |
| 188 ((distance_to_visible <= kFrequentInvalidationDistanceThreshold) || | |
| 189 (GetInvalidationFrequency() < kInvalidationFrequencyThreshold)); | |
| 190 } | |
| 191 | |
| 192 void PicturePileBase::PictureInfo::SetPicture(scoped_refptr<Picture> picture) { | |
| 193 picture_ = picture; | |
| 194 } | |
| 195 | |
| 196 const Picture* PicturePileBase::PictureInfo::GetPicture() const { | |
| 197 return picture_.get(); | |
| 198 } | |
| 199 | |
| 200 float PicturePileBase::PictureInfo::GetInvalidationFrequency() const { | |
| 201 return invalidation_history_.count() / | |
| 202 static_cast<float>(INVALIDATION_FRAMES_TRACKED); | |
| 203 } | |
| 204 | |
| 205 } // namespace cc | |
| OLD | NEW |