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