Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1 | // Copyright 2012 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/layers/picture_layer_impl.h" |
| 6 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 7 | #include <algorithm> |
| 8 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 9 | #include "base/time/time.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 10 | #include "cc/base/math_util.h" |
| 11 | #include "cc/base/util.h" |
| 12 | #include "cc/debug/debug_colors.h" |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 13 | #include "cc/debug/traced_value.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 14 | #include "cc/layers/append_quads_data.h" |
| 15 | #include "cc/layers/quad_sink.h" |
| 16 | #include "cc/quads/checkerboard_draw_quad.h" |
| 17 | #include "cc/quads/debug_border_draw_quad.h" |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 18 | #include "cc/quads/picture_draw_quad.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 19 | #include "cc/quads/solid_color_draw_quad.h" |
| 20 | #include "cc/quads/tile_draw_quad.h" |
| 21 | #include "cc/trees/layer_tree_impl.h" |
| 22 | #include "ui/gfx/quad_f.h" |
| 23 | #include "ui/gfx/rect_conversions.h" |
| 24 | #include "ui/gfx/size_conversions.h" |
| 25 | |
| 26 | namespace { |
| 27 | const float kMaxScaleRatioDuringPinch = 2.0f; |
| 28 | } |
| 29 | |
| 30 | namespace cc { |
| 31 | |
| 32 | PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) |
| 33 | : LayerImpl(tree_impl, id), |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 34 | twin_layer_(NULL), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 35 | pile_(PicturePileImpl::Create()), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 36 | last_content_scale_(0), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 37 | is_mask_(false), |
| 38 | ideal_page_scale_(0.f), |
| 39 | ideal_device_scale_(0.f), |
| 40 | ideal_source_scale_(0.f), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 41 | ideal_contents_scale_(0.f), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 42 | raster_page_scale_(0.f), |
| 43 | raster_device_scale_(0.f), |
| 44 | raster_source_scale_(0.f), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 45 | raster_contents_scale_(0.f), |
| 46 | low_res_raster_contents_scale_(0.f), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 47 | raster_source_scale_was_animating_(false), |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 48 | is_using_lcd_text_(tree_impl->settings().can_use_lcd_text) { |
| 49 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 50 | |
| 51 | PictureLayerImpl::~PictureLayerImpl() { |
| 52 | } |
| 53 | |
| 54 | const char* PictureLayerImpl::LayerTypeAsString() const { |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 55 | return "cc::PictureLayerImpl"; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( |
| 59 | LayerTreeImpl* tree_impl) { |
| 60 | return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); |
| 61 | } |
| 62 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 63 | void PictureLayerImpl::CreateTilingSetIfNeeded() { |
| 64 | DCHECK(layer_tree_impl()->IsPendingTree()); |
| 65 | if (!tilings_) |
| 66 | tilings_.reset(new PictureLayerTilingSet(this, bounds())); |
| 67 | } |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 68 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 69 | void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 70 | LayerImpl::PushPropertiesTo(base_layer); |
| 71 | |
| 72 | PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); |
| 73 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 74 | // When the pending tree pushes to the active tree, the pending twin |
| 75 | // disappears. |
| 76 | layer_impl->twin_layer_ = NULL; |
| 77 | twin_layer_ = NULL; |
| 78 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 79 | layer_impl->SetIsMask(is_mask_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 80 | layer_impl->pile_ = pile_; |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 81 | pile_ = NULL; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 82 | |
| 83 | layer_impl->tilings_.swap(tilings_); |
| 84 | layer_impl->tilings_->SetClient(layer_impl); |
| 85 | if (tilings_) |
| 86 | tilings_->SetClient(this); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 87 | |
| 88 | layer_impl->raster_page_scale_ = raster_page_scale_; |
| 89 | layer_impl->raster_device_scale_ = raster_device_scale_; |
| 90 | layer_impl->raster_source_scale_ = raster_source_scale_; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 91 | layer_impl->raster_contents_scale_ = raster_contents_scale_; |
| 92 | layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 93 | |
| 94 | layer_impl->UpdateLCDTextStatus(is_using_lcd_text_); |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 95 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 96 | // As an optimization, don't make a copy of this potentially complex region, |
| 97 | // and swap it directly from the pending to the active layer. In general, any |
| 98 | // property pushed to a LayerImpl continues to live on that LayerImpl. |
| 99 | // However, invalidation is the difference between two main thread frames, so |
| 100 | // it no longer makes sense once the pending tree gets recycled. It will |
| 101 | // always get pushed during PictureLayer::PushPropertiesTo. |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 102 | layer_impl->invalidation_.Swap(&invalidation_); |
| 103 | invalidation_.Clear(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 104 | } |
| 105 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 106 | void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, |
| 107 | AppendQuadsData* append_quads_data) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 108 | gfx::Rect rect(visible_content_rect()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 109 | gfx::Rect content_rect(content_bounds()); |
| 110 | |
| 111 | SharedQuadState* shared_quad_state = |
| 112 | quad_sink->UseSharedQuadState(CreateSharedQuadState()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 113 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 114 | bool draw_direct_to_backbuffer = |
| 115 | draw_properties().can_draw_directly_to_backbuffer && |
| 116 | layer_tree_impl()->settings().force_direct_layer_drawing; |
| 117 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 118 | if (draw_direct_to_backbuffer || |
| 119 | current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 120 | AppendDebugBorderQuad( |
| 121 | quad_sink, |
| 122 | shared_quad_state, |
| 123 | append_quads_data, |
| 124 | DebugColors::DirectPictureBorderColor(), |
| 125 | DebugColors::DirectPictureBorderWidth(layer_tree_impl())); |
| 126 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 127 | gfx::Rect geometry_rect = rect; |
| 128 | gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); |
| 129 | gfx::Size texture_size = rect.size(); |
| 130 | gfx::RectF texture_rect = gfx::RectF(texture_size); |
| 131 | gfx::Rect quad_content_rect = rect; |
| 132 | float contents_scale = contents_scale_x(); |
| 133 | |
| 134 | scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); |
| 135 | quad->SetNew(shared_quad_state, |
| 136 | geometry_rect, |
| 137 | opaque_rect, |
| 138 | texture_rect, |
| 139 | texture_size, |
| 140 | false, |
| 141 | quad_content_rect, |
| 142 | contents_scale, |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 143 | draw_direct_to_backbuffer, |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 144 | pile_); |
| 145 | if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) |
| 146 | append_quads_data->num_missing_tiles++; |
| 147 | return; |
| 148 | } |
| 149 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 150 | AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); |
| 151 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 152 | bool clipped = false; |
| 153 | gfx::QuadF target_quad = MathUtil::MapQuad( |
| 154 | draw_transform(), |
| 155 | gfx::QuadF(rect), |
| 156 | &clipped); |
| 157 | if (ShowDebugBorders()) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 158 | for (PictureLayerTilingSet::CoverageIterator iter( |
| 159 | tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 160 | iter; |
| 161 | ++iter) { |
| 162 | SkColor color; |
| 163 | float width; |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 164 | if (*iter && iter->IsReadyToDraw()) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 165 | ManagedTileState::TileVersion::Mode mode = |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 166 | iter->GetTileVersionForDrawing().mode(); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 167 | if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 168 | color = DebugColors::SolidColorTileBorderColor(); |
| 169 | width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl()); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 170 | } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 171 | color = DebugColors::PictureTileBorderColor(); |
| 172 | width = DebugColors::PictureTileBorderWidth(layer_tree_impl()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 173 | } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) { |
| 174 | color = DebugColors::HighResTileBorderColor(); |
| 175 | width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); |
| 176 | } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) { |
| 177 | color = DebugColors::LowResTileBorderColor(); |
| 178 | width = DebugColors::LowResTileBorderWidth(layer_tree_impl()); |
| 179 | } else if (iter->contents_scale() > contents_scale_x()) { |
| 180 | color = DebugColors::ExtraHighResTileBorderColor(); |
| 181 | width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl()); |
| 182 | } else { |
| 183 | color = DebugColors::ExtraLowResTileBorderColor(); |
| 184 | width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl()); |
| 185 | } |
| 186 | } else { |
| 187 | color = DebugColors::MissingTileBorderColor(); |
| 188 | width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); |
| 189 | } |
| 190 | |
| 191 | scoped_ptr<DebugBorderDrawQuad> debug_border_quad = |
| 192 | DebugBorderDrawQuad::Create(); |
| 193 | gfx::Rect geometry_rect = iter.geometry_rect(); |
| 194 | debug_border_quad->SetNew(shared_quad_state, geometry_rect, color, width); |
| 195 | quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), |
| 196 | append_quads_data); |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | // Keep track of the tilings that were used so that tilings that are |
| 201 | // unused can be considered for removal. |
| 202 | std::vector<PictureLayerTiling*> seen_tilings; |
| 203 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 204 | for (PictureLayerTilingSet::CoverageIterator iter( |
| 205 | tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 206 | iter; |
| 207 | ++iter) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 208 | gfx::Rect geometry_rect = iter.geometry_rect(); |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 209 | if (!*iter || !iter->IsReadyToDraw()) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 210 | if (DrawCheckerboardForMissingTiles()) { |
| 211 | // TODO(enne): Figure out how to show debug "invalidated checker" color |
| 212 | scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create(); |
| 213 | SkColor color = DebugColors::DefaultCheckerboardColor(); |
| 214 | quad->SetNew(shared_quad_state, geometry_rect, color); |
| 215 | if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 216 | append_quads_data->num_missing_tiles++; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 217 | } else { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 218 | SkColor color = SafeOpaqueBackgroundColor(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 219 | scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 220 | quad->SetNew(shared_quad_state, geometry_rect, color, false); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 221 | if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 222 | append_quads_data->num_missing_tiles++; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 223 | } |
| 224 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 225 | append_quads_data->had_incomplete_tile = true; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 226 | continue; |
| 227 | } |
| 228 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 229 | const ManagedTileState::TileVersion& tile_version = |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 230 | iter->GetTileVersionForDrawing(); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 231 | switch (tile_version.mode()) { |
| 232 | case ManagedTileState::TileVersion::RESOURCE_MODE: { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 233 | gfx::RectF texture_rect = iter.texture_rect(); |
| 234 | gfx::Rect opaque_rect = iter->opaque_rect(); |
| 235 | opaque_rect.Intersect(content_rect); |
| 236 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 237 | if (iter->contents_scale() != ideal_contents_scale_) |
| 238 | append_quads_data->had_incomplete_tile = true; |
| 239 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 240 | scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); |
| 241 | quad->SetNew(shared_quad_state, |
| 242 | geometry_rect, |
| 243 | opaque_rect, |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 244 | tile_version.get_resource_id(), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 245 | texture_rect, |
| 246 | iter.texture_size(), |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 247 | tile_version.contents_swizzled()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 248 | quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); |
| 249 | break; |
| 250 | } |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 251 | case ManagedTileState::TileVersion::PICTURE_PILE_MODE: { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 252 | gfx::RectF texture_rect = iter.texture_rect(); |
| 253 | gfx::Rect opaque_rect = iter->opaque_rect(); |
| 254 | opaque_rect.Intersect(content_rect); |
| 255 | |
| 256 | scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); |
| 257 | quad->SetNew(shared_quad_state, |
| 258 | geometry_rect, |
| 259 | opaque_rect, |
| 260 | texture_rect, |
| 261 | iter.texture_size(), |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 262 | // TODO(reveman): This assumes the renderer will use |
| 263 | // GL_RGBA as format of temporary resource. The need |
| 264 | // to swizzle should instead be determined by the |
| 265 | // renderer. |
| 266 | !PlatformColor::SameComponentOrder(GL_RGBA), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 267 | iter->content_rect(), |
| 268 | iter->contents_scale(), |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 269 | draw_direct_to_backbuffer, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 270 | pile_); |
| 271 | quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); |
| 272 | break; |
| 273 | } |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 274 | case ManagedTileState::TileVersion::SOLID_COLOR_MODE: { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 275 | scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); |
| 276 | quad->SetNew(shared_quad_state, |
| 277 | geometry_rect, |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 278 | tile_version.get_solid_color(), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 279 | false); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 280 | quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); |
| 281 | break; |
| 282 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 283 | default: |
| 284 | NOTREACHED(); |
| 285 | } |
| 286 | |
| 287 | if (!seen_tilings.size() || seen_tilings.back() != iter.CurrentTiling()) |
| 288 | seen_tilings.push_back(iter.CurrentTiling()); |
| 289 | } |
| 290 | |
| 291 | // Aggressively remove any tilings that are not seen to save memory. Note |
| 292 | // that this is at the expense of doing cause more frequent re-painting. A |
| 293 | // better scheme would be to maintain a tighter visible_content_rect for the |
| 294 | // finer tilings. |
| 295 | CleanUpTilingsOnActiveLayer(seen_tilings); |
| 296 | } |
| 297 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 298 | void PictureLayerImpl::UpdateTilePriorities() { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 299 | if (!tilings_->num_tilings()) |
| 300 | return; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 301 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 302 | double current_frame_time_in_seconds = |
| 303 | (layer_tree_impl()->CurrentFrameTimeTicks() - |
| 304 | base::TimeTicks()).InSecondsF(); |
| 305 | |
| 306 | bool tiling_needs_update = false; |
| 307 | for (size_t i = 0; i < tilings_->num_tilings(); ++i) { |
| 308 | if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime( |
| 309 | current_frame_time_in_seconds)) { |
| 310 | tiling_needs_update = true; |
| 311 | break; |
| 312 | } |
| 313 | } |
| 314 | if (!tiling_needs_update) |
| 315 | return; |
| 316 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 317 | // At this point, tile priorities are going to be modified. |
| 318 | layer_tree_impl()->WillModifyTilePriorities(); |
| 319 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 320 | UpdateLCDTextStatus(can_use_lcd_text()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 321 | |
| 322 | gfx::Transform current_screen_space_transform = screen_space_transform(); |
| 323 | |
| 324 | gfx::Rect viewport_in_content_space; |
| 325 | gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization); |
| 326 | if (screen_space_transform().GetInverse(&screen_to_layer)) { |
| 327 | gfx::Rect device_viewport(layer_tree_impl()->device_viewport_size()); |
| 328 | viewport_in_content_space = gfx::ToEnclosingRect( |
| 329 | MathUtil::ProjectClippedRect(screen_to_layer, device_viewport)); |
| 330 | } |
| 331 | |
| 332 | WhichTree tree = |
| 333 | layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 334 | size_t max_tiles_for_interest_area = |
| 335 | layer_tree_impl()->settings().max_tiles_for_interest_area; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 336 | tilings_->UpdateTilePriorities( |
| 337 | tree, |
| 338 | layer_tree_impl()->device_viewport_size(), |
| 339 | viewport_in_content_space, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 340 | visible_content_rect(), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 341 | last_bounds_, |
| 342 | bounds(), |
| 343 | last_content_scale_, |
| 344 | contents_scale_x(), |
| 345 | last_screen_space_transform_, |
| 346 | current_screen_space_transform, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 347 | current_frame_time_in_seconds, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 348 | max_tiles_for_interest_area); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 349 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 350 | if (layer_tree_impl()->IsPendingTree()) |
| 351 | MarkVisibleResourcesAsRequired(); |
| 352 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 353 | last_screen_space_transform_ = current_screen_space_transform; |
| 354 | last_bounds_ = bounds(); |
| 355 | last_content_scale_ = contents_scale_x(); |
| 356 | } |
| 357 | |
| 358 | void PictureLayerImpl::DidBecomeActive() { |
| 359 | LayerImpl::DidBecomeActive(); |
| 360 | tilings_->DidBecomeActive(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 361 | layer_tree_impl()->WillModifyTilePriorities(); |
| 362 | } |
| 363 | |
| 364 | void PictureLayerImpl::DidBeginTracing() { |
| 365 | pile_->DidBeginTracing(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 366 | } |
| 367 | |
| 368 | void PictureLayerImpl::DidLoseOutputSurface() { |
| 369 | if (tilings_) |
| 370 | tilings_->RemoveAllTilings(); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 371 | |
| 372 | ResetRasterScale(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 373 | } |
| 374 | |
| 375 | void PictureLayerImpl::CalculateContentsScale( |
| 376 | float ideal_contents_scale, |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 377 | float device_scale_factor, |
| 378 | float page_scale_factor, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 379 | bool animating_transform_to_screen, |
| 380 | float* contents_scale_x, |
| 381 | float* contents_scale_y, |
| 382 | gfx::Size* content_bounds) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 383 | if (!CanHaveTilings()) { |
| 384 | ideal_page_scale_ = page_scale_factor; |
| 385 | ideal_device_scale_ = device_scale_factor; |
| 386 | ideal_contents_scale_ = ideal_contents_scale; |
| 387 | ideal_source_scale_ = |
| 388 | ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_; |
| 389 | *contents_scale_x = ideal_contents_scale_; |
| 390 | *contents_scale_y = ideal_contents_scale_; |
| 391 | *content_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), |
| 392 | ideal_contents_scale_, |
| 393 | ideal_contents_scale_)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 394 | return; |
| 395 | } |
| 396 | |
| 397 | float min_contents_scale = MinimumContentsScale(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 398 | DCHECK_GT(min_contents_scale, 0.f); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 399 | float min_page_scale = layer_tree_impl()->min_page_scale_factor(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 400 | DCHECK_GT(min_page_scale, 0.f); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 401 | float min_device_scale = 1.f; |
| 402 | float min_source_scale = |
| 403 | min_contents_scale / min_page_scale / min_device_scale; |
| 404 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 405 | float ideal_page_scale = page_scale_factor; |
| 406 | float ideal_device_scale = device_scale_factor; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 407 | float ideal_source_scale = |
| 408 | ideal_contents_scale / ideal_page_scale / ideal_device_scale; |
| 409 | |
| 410 | ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale); |
| 411 | ideal_page_scale_ = ideal_page_scale; |
| 412 | ideal_device_scale_ = ideal_device_scale; |
| 413 | ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale); |
| 414 | |
| 415 | ManageTilings(animating_transform_to_screen); |
| 416 | |
| 417 | // The content scale and bounds for a PictureLayerImpl is somewhat fictitious. |
| 418 | // There are (usually) several tilings at different scales. However, the |
| 419 | // content bounds is the (integer!) space in which quads are generated. |
| 420 | // In order to guarantee that we can fill this integer space with any set of |
| 421 | // tilings (and then map back to floating point texture coordinates), the |
| 422 | // contents scale must be at least as large as the largest of the tilings. |
| 423 | float max_contents_scale = min_contents_scale; |
| 424 | for (size_t i = 0; i < tilings_->num_tilings(); ++i) { |
| 425 | const PictureLayerTiling* tiling = tilings_->tiling_at(i); |
| 426 | max_contents_scale = std::max(max_contents_scale, tiling->contents_scale()); |
| 427 | } |
| 428 | |
| 429 | *contents_scale_x = max_contents_scale; |
| 430 | *contents_scale_y = max_contents_scale; |
| 431 | *content_bounds = gfx::ToCeiledSize( |
| 432 | gfx::ScaleSize(bounds(), max_contents_scale, max_contents_scale)); |
| 433 | } |
| 434 | |
| 435 | skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() { |
| 436 | return pile_->GetFlattenedPicture(); |
| 437 | } |
| 438 | |
| 439 | scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling, |
| 440 | gfx::Rect content_rect) { |
| 441 | if (!pile_->CanRaster(tiling->contents_scale(), content_rect)) |
| 442 | return scoped_refptr<Tile>(); |
| 443 | |
| 444 | return make_scoped_refptr(new Tile( |
| 445 | layer_tree_impl()->tile_manager(), |
| 446 | pile_.get(), |
| 447 | content_rect.size(), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 448 | content_rect, |
| 449 | contents_opaque() ? content_rect : gfx::Rect(), |
| 450 | tiling->contents_scale(), |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 451 | id(), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 452 | layer_tree_impl()->source_frame_number(), |
| 453 | is_using_lcd_text_)); |
| 454 | } |
| 455 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 456 | void PictureLayerImpl::UpdatePile(Tile* tile) { |
| 457 | tile->set_picture_pile(pile_); |
| 458 | } |
| 459 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 460 | const Region* PictureLayerImpl::GetInvalidation() { |
| 461 | return &invalidation_; |
| 462 | } |
| 463 | |
| 464 | const PictureLayerTiling* PictureLayerImpl::GetTwinTiling( |
| 465 | const PictureLayerTiling* tiling) { |
| 466 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 467 | if (!twin_layer_) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 468 | return NULL; |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 469 | for (size_t i = 0; i < twin_layer_->tilings_->num_tilings(); ++i) |
| 470 | if (twin_layer_->tilings_->tiling_at(i)->contents_scale() == |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 471 | tiling->contents_scale()) |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 472 | return twin_layer_->tilings_->tiling_at(i); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 473 | return NULL; |
| 474 | } |
| 475 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 476 | gfx::Size PictureLayerImpl::CalculateTileSize( |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 477 | gfx::Size content_bounds) const { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 478 | if (is_mask_) { |
| 479 | int max_size = layer_tree_impl()->MaxTextureSize(); |
| 480 | return gfx::Size( |
| 481 | std::min(max_size, content_bounds.width()), |
| 482 | std::min(max_size, content_bounds.height())); |
| 483 | } |
| 484 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 485 | int max_texture_size = |
| 486 | layer_tree_impl()->resource_provider()->max_texture_size(); |
| 487 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 488 | gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 489 | default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size)); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 490 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 491 | gfx::Size max_untiled_content_size = |
| 492 | layer_tree_impl()->settings().max_untiled_layer_size; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 493 | max_untiled_content_size.SetToMin( |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 494 | gfx::Size(max_texture_size, max_texture_size)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 495 | |
| 496 | bool any_dimension_too_large = |
| 497 | content_bounds.width() > max_untiled_content_size.width() || |
| 498 | content_bounds.height() > max_untiled_content_size.height(); |
| 499 | |
| 500 | bool any_dimension_one_tile = |
| 501 | content_bounds.width() <= default_tile_size.width() || |
| 502 | content_bounds.height() <= default_tile_size.height(); |
| 503 | |
| 504 | // If long and skinny, tile at the max untiled content size, and clamp |
| 505 | // the smaller dimension to the content size, e.g. 1000x12 layer with |
| 506 | // 500x500 max untiled size would get 500x12 tiles. Also do this |
| 507 | // if the layer is small. |
| 508 | if (any_dimension_one_tile || !any_dimension_too_large) { |
| 509 | int width = |
| 510 | std::min(max_untiled_content_size.width(), content_bounds.width()); |
| 511 | int height = |
| 512 | std::min(max_untiled_content_size.height(), content_bounds.height()); |
| 513 | // Round width and height up to the closest multiple of 64, or 56 if |
| 514 | // we should avoid power-of-two textures. This helps reduce the number |
| 515 | // of different textures sizes to help recycling, and also keeps all |
| 516 | // textures multiple-of-eight, which is preferred on some drivers (IMG). |
| 517 | bool avoid_pow2 = |
| 518 | layer_tree_impl()->GetRendererCapabilities().avoid_pow2_textures; |
| 519 | int round_up_to = avoid_pow2 ? 56 : 64; |
| 520 | width = RoundUp(width, round_up_to); |
| 521 | height = RoundUp(height, round_up_to); |
| 522 | return gfx::Size(width, height); |
| 523 | } |
| 524 | |
| 525 | return default_tile_size; |
| 526 | } |
| 527 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 528 | void PictureLayerImpl::SyncFromActiveLayer() { |
| 529 | DCHECK(layer_tree_impl()->IsPendingTree()); |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 530 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 531 | if (twin_layer_) |
| 532 | SyncFromActiveLayer(twin_layer_); |
| 533 | } |
| 534 | |
| 535 | void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 536 | UpdateLCDTextStatus(other->is_using_lcd_text_); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 537 | |
| 538 | if (!DrawsContent()) { |
| 539 | ResetRasterScale(); |
| 540 | return; |
| 541 | } |
| 542 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 543 | raster_page_scale_ = other->raster_page_scale_; |
| 544 | raster_device_scale_ = other->raster_device_scale_; |
| 545 | raster_source_scale_ = other->raster_source_scale_; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 546 | raster_contents_scale_ = other->raster_contents_scale_; |
| 547 | low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 548 | |
| 549 | // Add synthetic invalidations for any recordings that were dropped. As |
| 550 | // tiles are updated to point to this new pile, this will force the dropping |
| 551 | // of tiles that can no longer be rastered. This is not ideal, but is a |
| 552 | // trade-off for memory (use the same pile as much as possible, by switching |
| 553 | // during DidBecomeActive) and for time (don't bother checking every tile |
| 554 | // during activation to see if the new pile can still raster it). |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 555 | for (int x = 0; x < pile_->num_tiles_x(); ++x) { |
| 556 | for (int y = 0; y < pile_->num_tiles_y(); ++y) { |
| 557 | bool previously_had = other->pile_->HasRecordingAt(x, y); |
| 558 | bool now_has = pile_->HasRecordingAt(x, y); |
| 559 | if (now_has || !previously_had) |
| 560 | continue; |
| 561 | gfx::Rect layer_rect = pile_->tile_bounds(x, y); |
| 562 | invalidation_.Union(layer_rect); |
| 563 | } |
| 564 | } |
| 565 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 566 | // Union in the other newly exposed regions as invalid. |
| 567 | Region difference_region = Region(gfx::Rect(bounds())); |
| 568 | difference_region.Subtract(gfx::Rect(other->bounds())); |
| 569 | invalidation_.Union(difference_region); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 570 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 571 | if (CanHaveTilings()) { |
| 572 | // The recycle tree's tiling set is two frames out of date, so it needs to |
| 573 | // have both this frame's invalidation and the previous frame's invalidation |
| 574 | // (stored on the active layer). |
| 575 | Region tiling_invalidation = other->invalidation_; |
| 576 | tiling_invalidation.Union(invalidation_); |
| 577 | tilings_->SyncTilings(*other->tilings_, |
| 578 | bounds(), |
| 579 | tiling_invalidation, |
| 580 | MinimumContentsScale()); |
| 581 | } else { |
| 582 | tilings_->RemoveAllTilings(); |
| 583 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 584 | } |
| 585 | |
| 586 | void PictureLayerImpl::SyncTiling( |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 587 | const PictureLayerTiling* tiling) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 588 | if (!CanHaveTilingWithScale(tiling->contents_scale())) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 589 | return; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 590 | tilings_->AddTiling(tiling->contents_scale()); |
| 591 | |
| 592 | // If this tree needs update draw properties, then the tiling will |
| 593 | // get updated prior to drawing or activation. If this tree does not |
| 594 | // need update draw properties, then its transforms are up to date and |
| 595 | // we can create tiles for this tiling immediately. |
| 596 | if (!layer_tree_impl()->needs_update_draw_properties()) |
| 597 | UpdateTilePriorities(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 598 | } |
| 599 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 600 | void PictureLayerImpl::UpdateTwinLayer() { |
| 601 | DCHECK(layer_tree_impl()->IsPendingTree()); |
| 602 | |
| 603 | twin_layer_ = static_cast<PictureLayerImpl*>( |
| 604 | layer_tree_impl()->FindActiveTreeLayerById(id())); |
| 605 | if (twin_layer_) |
| 606 | twin_layer_->twin_layer_ = this; |
| 607 | } |
| 608 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 609 | void PictureLayerImpl::SetIsMask(bool is_mask) { |
| 610 | if (is_mask_ == is_mask) |
| 611 | return; |
| 612 | is_mask_ = is_mask; |
| 613 | if (tilings_) |
| 614 | tilings_->RemoveAllTiles(); |
| 615 | } |
| 616 | |
| 617 | ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const { |
| 618 | gfx::Rect content_rect(content_bounds()); |
| 619 | float scale = contents_scale_x(); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 620 | for (PictureLayerTilingSet::CoverageIterator |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 621 | iter(tilings_.get(), scale, content_rect, ideal_contents_scale_); |
| 622 | iter; |
| 623 | ++iter) { |
| 624 | // Mask resource not ready yet. |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 625 | if (!*iter) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 626 | return 0; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 627 | |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 628 | const ManagedTileState::TileVersion& tile_version = |
| 629 | iter->GetTileVersionForDrawing(); |
| 630 | if (!tile_version.IsReadyToDraw() || |
| 631 | tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE) |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 632 | return 0; |
| 633 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 634 | // Masks only supported if they fit on exactly one tile. |
| 635 | if (iter.geometry_rect() != content_rect) |
| 636 | return 0; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 637 | |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 638 | return tile_version.get_resource_id(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 639 | } |
| 640 | return 0; |
| 641 | } |
| 642 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 643 | void PictureLayerImpl::MarkVisibleResourcesAsRequired() const { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 644 | DCHECK(layer_tree_impl()->IsPendingTree()); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 645 | DCHECK(!layer_tree_impl()->needs_update_draw_properties()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 646 | DCHECK(ideal_contents_scale_); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 647 | DCHECK_GT(tilings_->num_tilings(), 0u); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 648 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 649 | gfx::Rect rect(visible_content_rect()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 650 | |
| 651 | float min_acceptable_scale = |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 652 | std::min(raster_contents_scale_, ideal_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 653 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 654 | if (PictureLayerImpl* twin = twin_layer_) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 655 | float twin_min_acceptable_scale = |
| 656 | std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_); |
| 657 | // Ignore 0 scale in case CalculateContentsScale() has never been |
| 658 | // called for active twin. |
| 659 | if (twin_min_acceptable_scale != 0.0f) { |
| 660 | min_acceptable_scale = |
| 661 | std::min(min_acceptable_scale, twin_min_acceptable_scale); |
| 662 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 663 | } |
| 664 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 665 | // Mark tiles for activation in two passes. Ready to draw tiles in acceptable |
| 666 | // but non-ideal tilings are marked as required for activation, but any |
| 667 | // non-ready tiles are not marked as required. From there, any missing holes |
| 668 | // will need to be filled in from the high res tiling. |
| 669 | |
| 670 | PictureLayerTiling* high_res = NULL; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 671 | Region missing_region = rect; |
| 672 | for (size_t i = 0; i < tilings_->num_tilings(); ++i) { |
| 673 | PictureLayerTiling* tiling = tilings_->tiling_at(i); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 674 | DCHECK(tiling->has_ever_been_updated()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 675 | |
| 676 | if (tiling->contents_scale() < min_acceptable_scale) |
| 677 | continue; |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 678 | if (tiling->resolution() == HIGH_RESOLUTION) { |
| 679 | DCHECK(!high_res) << "There can only be one high res tiling"; |
| 680 | high_res = tiling; |
| 681 | continue; |
| 682 | } |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 683 | for (PictureLayerTiling::CoverageIterator iter(tiling, |
| 684 | contents_scale_x(), |
| 685 | rect); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 686 | iter; |
| 687 | ++iter) { |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 688 | if (!*iter || !iter->IsReadyToDraw()) |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 689 | continue; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 690 | |
| 691 | // This iteration is over the visible content rect which is potentially |
| 692 | // less conservative than projecting the viewport into the layer. |
| 693 | // Ignore tiles that are know to be outside the viewport. |
| 694 | if (iter->priority(PENDING_TREE).distance_to_visible_in_pixels != 0) |
| 695 | continue; |
| 696 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 697 | missing_region.Subtract(iter.geometry_rect()); |
| 698 | iter->mark_required_for_activation(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 699 | } |
| 700 | } |
| 701 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 702 | DCHECK(high_res) << "There must be one high res tiling"; |
| 703 | for (PictureLayerTiling::CoverageIterator iter(high_res, |
| 704 | contents_scale_x(), |
| 705 | rect); |
| 706 | iter; |
| 707 | ++iter) { |
| 708 | // A null tile (i.e. missing recording) can just be skipped. |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 709 | if (!*iter) |
| 710 | continue; |
| 711 | |
| 712 | // This iteration is over the visible content rect which is potentially |
| 713 | // less conservative than projecting the viewport into the layer. |
| 714 | // Ignore tiles that are know to be outside the viewport. |
| 715 | if (iter->priority(PENDING_TREE).distance_to_visible_in_pixels != 0) |
| 716 | continue; |
| 717 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 718 | // If the missing region doesn't cover it, this tile is fully |
| 719 | // covered by acceptable tiles at other scales. |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 720 | if (!missing_region.Intersects(iter.geometry_rect())) |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 721 | continue; |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 722 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 723 | iter->mark_required_for_activation(); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 724 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 725 | } |
| 726 | |
| 727 | PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 728 | DCHECK(CanHaveTilingWithScale(contents_scale)) << |
| 729 | "contents_scale: " << contents_scale; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 730 | |
| 731 | PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale); |
| 732 | |
| 733 | const Region& recorded = pile_->recorded_region(); |
| 734 | DCHECK(!recorded.IsEmpty()); |
| 735 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 736 | if (twin_layer_) |
| 737 | twin_layer_->SyncTiling(tiling); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 738 | |
| 739 | return tiling; |
| 740 | } |
| 741 | |
| 742 | void PictureLayerImpl::RemoveTiling(float contents_scale) { |
| 743 | for (size_t i = 0; i < tilings_->num_tilings(); ++i) { |
| 744 | PictureLayerTiling* tiling = tilings_->tiling_at(i); |
| 745 | if (tiling->contents_scale() == contents_scale) { |
| 746 | tilings_->Remove(tiling); |
| 747 | break; |
| 748 | } |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | namespace { |
| 753 | |
| 754 | inline float PositiveRatio(float float1, float float2) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 755 | DCHECK_GT(float1, 0); |
| 756 | DCHECK_GT(float2, 0); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 757 | return float1 > float2 ? float1 / float2 : float2 / float1; |
| 758 | } |
| 759 | |
| 760 | inline bool IsCloserToThan( |
| 761 | PictureLayerTiling* layer1, |
| 762 | PictureLayerTiling* layer2, |
| 763 | float contents_scale) { |
| 764 | // Absolute value for ratios. |
| 765 | float ratio1 = PositiveRatio(layer1->contents_scale(), contents_scale); |
| 766 | float ratio2 = PositiveRatio(layer2->contents_scale(), contents_scale); |
| 767 | return ratio1 < ratio2; |
| 768 | } |
| 769 | |
| 770 | } // namespace |
| 771 | |
| 772 | void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) { |
| 773 | DCHECK(ideal_contents_scale_); |
| 774 | DCHECK(ideal_page_scale_); |
| 775 | DCHECK(ideal_device_scale_); |
| 776 | DCHECK(ideal_source_scale_); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 777 | DCHECK(CanHaveTilings()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 778 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 779 | bool change_target_tiling = |
| 780 | raster_page_scale_ == 0.f || |
| 781 | raster_device_scale_ == 0.f || |
| 782 | raster_source_scale_ == 0.f || |
| 783 | raster_contents_scale_ == 0.f || |
| 784 | low_res_raster_contents_scale_ == 0.f || |
| 785 | ShouldAdjustRasterScale(animating_transform_to_screen); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 786 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 787 | // Store the value for the next time ShouldAdjustRasterScale is called. |
| 788 | raster_source_scale_was_animating_ = animating_transform_to_screen; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 789 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 790 | if (!change_target_tiling) |
| 791 | return; |
| 792 | |
| 793 | raster_page_scale_ = ideal_page_scale_; |
| 794 | raster_device_scale_ = ideal_device_scale_; |
| 795 | raster_source_scale_ = ideal_source_scale_; |
| 796 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 797 | CalculateRasterContentsScale(animating_transform_to_screen, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 798 | &raster_contents_scale_, |
| 799 | &low_res_raster_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 800 | |
| 801 | PictureLayerTiling* high_res = NULL; |
| 802 | PictureLayerTiling* low_res = NULL; |
| 803 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 804 | PictureLayerTiling* previous_low_res = NULL; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 805 | for (size_t i = 0; i < tilings_->num_tilings(); ++i) { |
| 806 | PictureLayerTiling* tiling = tilings_->tiling_at(i); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 807 | if (tiling->contents_scale() == raster_contents_scale_) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 808 | high_res = tiling; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 809 | if (tiling->contents_scale() == low_res_raster_contents_scale_) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 810 | low_res = tiling; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 811 | if (tiling->resolution() == LOW_RESOLUTION) |
| 812 | previous_low_res = tiling; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 813 | |
| 814 | // Reset all tilings to non-ideal until the end of this function. |
| 815 | tiling->set_resolution(NON_IDEAL_RESOLUTION); |
| 816 | } |
| 817 | |
| 818 | if (!high_res) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 819 | high_res = AddTiling(raster_contents_scale_); |
| 820 | if (raster_contents_scale_ == low_res_raster_contents_scale_) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 821 | low_res = high_res; |
| 822 | } |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 823 | |
| 824 | // Only create new low res tilings when the transform is static. This |
| 825 | // prevents wastefully creating a paired low res tiling for every new high res |
| 826 | // tiling during a pinch or a CSS animation. |
| 827 | bool is_pinching = layer_tree_impl()->PinchGestureActive(); |
| 828 | if (!is_pinching && !animating_transform_to_screen && !low_res && |
| 829 | low_res != high_res) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 830 | low_res = AddTiling(low_res_raster_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 831 | |
| 832 | if (high_res) |
| 833 | high_res->set_resolution(HIGH_RESOLUTION); |
| 834 | if (low_res && low_res != high_res) |
| 835 | low_res->set_resolution(LOW_RESOLUTION); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 836 | else if (!low_res && previous_low_res) |
| 837 | previous_low_res->set_resolution(LOW_RESOLUTION); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 838 | } |
| 839 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 840 | bool PictureLayerImpl::ShouldAdjustRasterScale( |
| 841 | bool animating_transform_to_screen) const { |
| 842 | // TODO(danakj): Adjust raster source scale closer to ideal source scale at |
| 843 | // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending |
| 844 | // tree. This will allow CSS scale changes to get re-rastered at an |
| 845 | // appropriate rate. |
| 846 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 847 | if (raster_source_scale_was_animating_ && !animating_transform_to_screen) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 848 | return true; |
| 849 | |
| 850 | bool is_pinching = layer_tree_impl()->PinchGestureActive(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 851 | if (is_pinching && raster_page_scale_) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 852 | // If the page scale diverges too far during pinch, change raster target to |
| 853 | // the current page scale. |
| 854 | float ratio = PositiveRatio(ideal_page_scale_, raster_page_scale_); |
| 855 | if (ratio >= kMaxScaleRatioDuringPinch) |
| 856 | return true; |
| 857 | } |
| 858 | |
| 859 | if (!is_pinching) { |
| 860 | // When not pinching, match the ideal page scale factor. |
| 861 | if (raster_page_scale_ != ideal_page_scale_) |
| 862 | return true; |
| 863 | } |
| 864 | |
| 865 | // Always match the ideal device scale factor. |
| 866 | if (raster_device_scale_ != ideal_device_scale_) |
| 867 | return true; |
| 868 | |
| 869 | return false; |
| 870 | } |
| 871 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 872 | void PictureLayerImpl::CalculateRasterContentsScale( |
| 873 | bool animating_transform_to_screen, |
| 874 | float* raster_contents_scale, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 875 | float* low_res_raster_contents_scale) const { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 876 | *raster_contents_scale = ideal_contents_scale_; |
| 877 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 878 | // Don't allow animating CSS scales to drop below 1. This is needed because |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 879 | // changes in raster source scale aren't handled. See the comment in |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 880 | // ShouldAdjustRasterScale. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 881 | if (animating_transform_to_screen) { |
| 882 | *raster_contents_scale = std::max( |
| 883 | *raster_contents_scale, 1.f * ideal_page_scale_ * ideal_device_scale_); |
| 884 | } |
| 885 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 886 | // If this layer would only create one tile at this content scale, |
| 887 | // don't create a low res tiling. |
| 888 | gfx::Size content_bounds = |
| 889 | gfx::ToCeiledSize(gfx::ScaleSize(bounds(), *raster_contents_scale)); |
| 890 | gfx::Size tile_size = CalculateTileSize(content_bounds); |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 891 | if (tile_size.width() >= content_bounds.width() && |
| 892 | tile_size.height() >= content_bounds.height()) { |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 893 | *low_res_raster_contents_scale = *raster_contents_scale; |
| 894 | return; |
| 895 | } |
| 896 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 897 | float low_res_factor = |
| 898 | layer_tree_impl()->settings().low_res_contents_scale_factor; |
| 899 | *low_res_raster_contents_scale = std::max( |
| 900 | *raster_contents_scale * low_res_factor, |
| 901 | MinimumContentsScale()); |
| 902 | } |
| 903 | |
| 904 | void PictureLayerImpl::CleanUpTilingsOnActiveLayer( |
| 905 | std::vector<PictureLayerTiling*> used_tilings) { |
| 906 | DCHECK(layer_tree_impl()->IsActiveTree()); |
| 907 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 908 | float min_acceptable_high_res_scale = std::min( |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 909 | raster_contents_scale_, ideal_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 910 | float max_acceptable_high_res_scale = std::max( |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 911 | raster_contents_scale_, ideal_contents_scale_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 912 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 913 | PictureLayerImpl* twin = twin_layer_; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 914 | if (twin) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 915 | min_acceptable_high_res_scale = std::min( |
| 916 | min_acceptable_high_res_scale, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 917 | std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 918 | max_acceptable_high_res_scale = std::max( |
| 919 | max_acceptable_high_res_scale, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 920 | std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 921 | } |
| 922 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 923 | std::vector<PictureLayerTiling*> to_remove; |
| 924 | for (size_t i = 0; i < tilings_->num_tilings(); ++i) { |
| 925 | PictureLayerTiling* tiling = tilings_->tiling_at(i); |
| 926 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 927 | // Keep multiple high resolution tilings even if not used to help |
| 928 | // activate earlier at non-ideal resolutions. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 929 | if (tiling->contents_scale() >= min_acceptable_high_res_scale && |
| 930 | tiling->contents_scale() <= max_acceptable_high_res_scale) |
| 931 | continue; |
| 932 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 933 | // Low resolution can't activate, so only keep one around. |
| 934 | if (tiling->resolution() == LOW_RESOLUTION) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 935 | continue; |
| 936 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 937 | // Don't remove tilings that are being used (and thus would cause a flash.) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 938 | if (std::find(used_tilings.begin(), used_tilings.end(), tiling) != |
| 939 | used_tilings.end()) |
| 940 | continue; |
| 941 | |
| 942 | to_remove.push_back(tiling); |
| 943 | } |
| 944 | |
| 945 | for (size_t i = 0; i < to_remove.size(); ++i) { |
| 946 | if (twin) |
| 947 | twin->RemoveTiling(to_remove[i]->contents_scale()); |
| 948 | tilings_->Remove(to_remove[i]); |
| 949 | } |
| 950 | } |
| 951 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 952 | float PictureLayerImpl::MinimumContentsScale() const { |
| 953 | float setting_min = layer_tree_impl()->settings().minimum_contents_scale; |
| 954 | |
| 955 | // If the contents scale is less than 1 / width (also for height), |
| 956 | // then it will end up having less than one pixel of content in that |
| 957 | // dimension. Bump the minimum contents scale up in this case to prevent |
| 958 | // this from happening. |
| 959 | int min_dimension = std::min(bounds().width(), bounds().height()); |
| 960 | if (!min_dimension) |
| 961 | return setting_min; |
| 962 | |
| 963 | return std::max(1.f / min_dimension, setting_min); |
| 964 | } |
| 965 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 966 | void PictureLayerImpl::UpdateLCDTextStatus(bool new_status) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 967 | // Once this layer is not using lcd text, don't switch back. |
| 968 | if (!is_using_lcd_text_) |
| 969 | return; |
| 970 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 971 | if (is_using_lcd_text_ == new_status) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 972 | return; |
| 973 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 974 | is_using_lcd_text_ = new_status; |
| 975 | tilings_->SetCanUseLCDText(is_using_lcd_text_); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 976 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 977 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 978 | void PictureLayerImpl::ResetRasterScale() { |
| 979 | raster_page_scale_ = 0.f; |
| 980 | raster_device_scale_ = 0.f; |
| 981 | raster_source_scale_ = 0.f; |
| 982 | raster_contents_scale_ = 0.f; |
| 983 | low_res_raster_contents_scale_ = 0.f; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 984 | } |
| 985 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 986 | bool PictureLayerImpl::CanHaveTilings() const { |
| 987 | if (!DrawsContent()) |
| 988 | return false; |
| 989 | if (pile_->recorded_region().IsEmpty()) |
| 990 | return false; |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 991 | if (draw_properties().can_draw_directly_to_backbuffer && |
| 992 | layer_tree_impl()->settings().force_direct_layer_drawing) |
| 993 | return false; |
| 994 | return true; |
| 995 | } |
| 996 | |
| 997 | bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const { |
| 998 | if (!CanHaveTilings()) |
| 999 | return false; |
| 1000 | if (contents_scale < MinimumContentsScale()) |
| 1001 | return false; |
| 1002 | return true; |
| 1003 | } |
| 1004 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1005 | void PictureLayerImpl::GetDebugBorderProperties( |
| 1006 | SkColor* color, |
| 1007 | float* width) const { |
| 1008 | *color = DebugColors::TiledContentLayerBorderColor(); |
| 1009 | *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); |
| 1010 | } |
| 1011 | |
Torne (Richard Coles) | b2df76e | 2013-05-13 16:52:09 +0100 | [diff] [blame] | 1012 | void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const { |
| 1013 | LayerImpl::AsValueInto(state); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1014 | state->SetDouble("ideal_contents_scale", ideal_contents_scale_); |
| 1015 | state->Set("tilings", tilings_->AsValue().release()); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 1016 | state->Set("pictures", pile_->AsValue().release()); |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 1017 | state->Set("invalidation", invalidation_.AsValue().release()); |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 1018 | |
| 1019 | scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue); |
| 1020 | for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(), |
| 1021 | contents_scale_x(), |
| 1022 | gfx::Rect(bounds()), |
| 1023 | ideal_contents_scale_); |
| 1024 | iter; |
| 1025 | ++iter) { |
| 1026 | scoped_ptr<base::DictionaryValue> tile_data(new base::DictionaryValue); |
| 1027 | tile_data->Set("geometry_rect", |
| 1028 | MathUtil::AsValue(iter.geometry_rect()).release()); |
| 1029 | if (*iter) |
| 1030 | tile_data->Set("tile", TracedValue::CreateIDRef(*iter).release()); |
| 1031 | |
| 1032 | coverage_tiles->Append(tile_data.release()); |
| 1033 | } |
| 1034 | state->Set("coverage_tiles", coverage_tiles.release()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1035 | } |
| 1036 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 1037 | size_t PictureLayerImpl::GPUMemoryUsageInBytes() const { |
| 1038 | return tilings_->GPUMemoryUsageInBytes(); |
| 1039 | } |
| 1040 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1041 | } // namespace cc |