blob: 2f1878bc3a6b9b5adb4b7360d52b0f360a176272 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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)c2e0dbd2013-05-09 18:35:53 +01007#include <algorithm>
8
Ben Murdocheb525c52013-07-10 11:40:50 +01009#include "base/time/time.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include "cc/base/math_util.h"
11#include "cc/base/util.h"
12#include "cc/debug/debug_colors.h"
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010013#include "cc/debug/traced_value.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000014#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)c2e0dbd2013-05-09 18:35:53 +010018#include "cc/quads/picture_draw_quad.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000019#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
26namespace {
27const float kMaxScaleRatioDuringPinch = 2.0f;
28}
29
30namespace cc {
31
32PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
33 : LayerImpl(tree_impl, id),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010034 twin_layer_(NULL),
Ben Murdocheb525c52013-07-10 11:40:50 +010035 pile_(PicturePileImpl::Create()),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000036 last_content_scale_(0),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000037 is_mask_(false),
38 ideal_page_scale_(0.f),
39 ideal_device_scale_(0.f),
40 ideal_source_scale_(0.f),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010041 ideal_contents_scale_(0.f),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000042 raster_page_scale_(0.f),
43 raster_device_scale_(0.f),
44 raster_source_scale_(0.f),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010045 raster_contents_scale_(0.f),
46 low_res_raster_contents_scale_(0.f),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000047 raster_source_scale_was_animating_(false),
Ben Murdochbb1529c2013-08-08 10:24:53 +010048 is_using_lcd_text_(tree_impl->settings().can_use_lcd_text) {
49}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000050
51PictureLayerImpl::~PictureLayerImpl() {
52}
53
54const char* PictureLayerImpl::LayerTypeAsString() const {
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010055 return "cc::PictureLayerImpl";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000056}
57
58scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
59 LayerTreeImpl* tree_impl) {
60 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
61}
62
Ben Murdochbb1529c2013-08-08 10:24:53 +010063void PictureLayerImpl::CreateTilingSetIfNeeded() {
64 DCHECK(layer_tree_impl()->IsPendingTree());
65 if (!tilings_)
66 tilings_.reset(new PictureLayerTilingSet(this, bounds()));
67}
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010068
Ben Murdochbb1529c2013-08-08 10:24:53 +010069void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070 LayerImpl::PushPropertiesTo(base_layer);
71
72 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
73
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010074 // 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)2a99a7e2013-03-28 15:31:22 +000079 layer_impl->SetIsMask(is_mask_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000080 layer_impl->pile_ = pile_;
Ben Murdochbb1529c2013-08-08 10:24:53 +010081 pile_ = NULL;
Ben Murdocheb525c52013-07-10 11:40:50 +010082
83 layer_impl->tilings_.swap(tilings_);
84 layer_impl->tilings_->SetClient(layer_impl);
85 if (tilings_)
86 tilings_->SetClient(this);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000087
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)c2e0dbd2013-05-09 18:35:53 +010091 layer_impl->raster_contents_scale_ = raster_contents_scale_;
92 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
Ben Murdocheb525c52013-07-10 11:40:50 +010093
94 layer_impl->UpdateLCDTextStatus(is_using_lcd_text_);
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +010095
Ben Murdochbb1529c2013-08-08 10:24:53 +010096 // 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)a93a17c2013-05-15 11:34:50 +0100102 layer_impl->invalidation_.Swap(&invalidation_);
103 invalidation_.Clear();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000104}
105
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000106void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
107 AppendQuadsData* append_quads_data) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100108 gfx::Rect rect(visible_content_rect());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000109 gfx::Rect content_rect(content_bounds());
110
111 SharedQuadState* shared_quad_state =
112 quad_sink->UseSharedQuadState(CreateSharedQuadState());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000113
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100114 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)868fa2f2013-06-11 10:57:03 +0100118 if (draw_direct_to_backbuffer ||
119 current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100120 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)b2df76e2013-05-13 16:52:09 +0100127 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)90dce4d2013-05-29 14:40:03 +0100143 draw_direct_to_backbuffer,
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100144 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)90dce4d2013-05-29 14:40:03 +0100150 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
151
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000152 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)c2e0dbd2013-05-09 18:35:53 +0100158 for (PictureLayerTilingSet::CoverageIterator iter(
159 tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000160 iter;
161 ++iter) {
162 SkColor color;
163 float width;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100164 if (*iter && iter->IsReadyToDraw()) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100165 ManagedTileState::TileVersion::Mode mode =
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100166 iter->GetTileVersionForDrawing().mode();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100167 if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000168 color = DebugColors::SolidColorTileBorderColor();
169 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100170 } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100171 color = DebugColors::PictureTileBorderColor();
172 width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000173 } 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)c2e0dbd2013-05-09 18:35:53 +0100204 for (PictureLayerTilingSet::CoverageIterator iter(
205 tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000206 iter;
207 ++iter) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000208 gfx::Rect geometry_rect = iter.geometry_rect();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100209 if (!*iter || !iter->IsReadyToDraw()) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000210 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)c2e0dbd2013-05-09 18:35:53 +0100216 append_quads_data->num_missing_tiles++;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000217 } else {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100218 SkColor color = SafeOpaqueBackgroundColor();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000219 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100220 quad->SetNew(shared_quad_state, geometry_rect, color, false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000221 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data))
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100222 append_quads_data->num_missing_tiles++;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000223 }
224
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100225 append_quads_data->had_incomplete_tile = true;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000226 continue;
227 }
228
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100229 const ManagedTileState::TileVersion& tile_version =
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100230 iter->GetTileVersionForDrawing();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100231 switch (tile_version.mode()) {
232 case ManagedTileState::TileVersion::RESOURCE_MODE: {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000233 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)c2e0dbd2013-05-09 18:35:53 +0100237 if (iter->contents_scale() != ideal_contents_scale_)
238 append_quads_data->had_incomplete_tile = true;
239
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000240 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
241 quad->SetNew(shared_quad_state,
242 geometry_rect,
243 opaque_rect,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100244 tile_version.get_resource_id(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000245 texture_rect,
246 iter.texture_size(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100247 tile_version.contents_swizzled());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000248 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
249 break;
250 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100251 case ManagedTileState::TileVersion::PICTURE_PILE_MODE: {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100252 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)7d4cd472013-06-19 11:58:07 +0100262 // 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)c2e0dbd2013-05-09 18:35:53 +0100267 iter->content_rect(),
268 iter->contents_scale(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100269 draw_direct_to_backbuffer,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100270 pile_);
271 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
272 break;
273 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100274 case ManagedTileState::TileVersion::SOLID_COLOR_MODE: {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000275 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
276 quad->SetNew(shared_quad_state,
277 geometry_rect,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100278 tile_version.get_solid_color(),
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100279 false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000280 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
281 break;
282 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000283 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)2a99a7e2013-03-28 15:31:22 +0000298void PictureLayerImpl::UpdateTilePriorities() {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100299 if (!tilings_->num_tilings())
300 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000301
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100302 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)90dce4d2013-05-29 14:40:03 +0100317 // At this point, tile priorities are going to be modified.
318 layer_tree_impl()->WillModifyTilePriorities();
319
Ben Murdocheb525c52013-07-10 11:40:50 +0100320 UpdateLCDTextStatus(can_use_lcd_text());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000321
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)c2e0dbd2013-05-09 18:35:53 +0100334 size_t max_tiles_for_interest_area =
335 layer_tree_impl()->settings().max_tiles_for_interest_area;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000336 tilings_->UpdateTilePriorities(
337 tree,
338 layer_tree_impl()->device_viewport_size(),
339 viewport_in_content_space,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100340 visible_content_rect(),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000341 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)c2e0dbd2013-05-09 18:35:53 +0100347 current_frame_time_in_seconds,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100348 max_tiles_for_interest_area);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000349
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100350 if (layer_tree_impl()->IsPendingTree())
351 MarkVisibleResourcesAsRequired();
352
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000353 last_screen_space_transform_ = current_screen_space_transform;
354 last_bounds_ = bounds();
355 last_content_scale_ = contents_scale_x();
356}
357
358void PictureLayerImpl::DidBecomeActive() {
359 LayerImpl::DidBecomeActive();
360 tilings_->DidBecomeActive();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100361 layer_tree_impl()->WillModifyTilePriorities();
362}
363
364void PictureLayerImpl::DidBeginTracing() {
365 pile_->DidBeginTracing();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000366}
367
368void PictureLayerImpl::DidLoseOutputSurface() {
369 if (tilings_)
370 tilings_->RemoveAllTilings();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100371
372 ResetRasterScale();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000373}
374
375void PictureLayerImpl::CalculateContentsScale(
376 float ideal_contents_scale,
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100377 float device_scale_factor,
378 float page_scale_factor,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000379 bool animating_transform_to_screen,
380 float* contents_scale_x,
381 float* contents_scale_y,
382 gfx::Size* content_bounds) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100383 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)2a99a7e2013-03-28 15:31:22 +0000394 return;
395 }
396
397 float min_contents_scale = MinimumContentsScale();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100398 DCHECK_GT(min_contents_scale, 0.f);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000399 float min_page_scale = layer_tree_impl()->min_page_scale_factor();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100400 DCHECK_GT(min_page_scale, 0.f);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000401 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)b2df76e2013-05-13 16:52:09 +0100405 float ideal_page_scale = page_scale_factor;
406 float ideal_device_scale = device_scale_factor;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000407 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
435skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
436 return pile_->GetFlattenedPicture();
437}
438
439scoped_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)2a99a7e2013-03-28 15:31:22 +0000448 content_rect,
449 contents_opaque() ? content_rect : gfx::Rect(),
450 tiling->contents_scale(),
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100451 id(),
Ben Murdocheb525c52013-07-10 11:40:50 +0100452 layer_tree_impl()->source_frame_number(),
453 is_using_lcd_text_));
454}
455
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000456void PictureLayerImpl::UpdatePile(Tile* tile) {
457 tile->set_picture_pile(pile_);
458}
459
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100460const Region* PictureLayerImpl::GetInvalidation() {
461 return &invalidation_;
462}
463
464const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
465 const PictureLayerTiling* tiling) {
466
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100467 if (!twin_layer_)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100468 return NULL;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100469 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)c2e0dbd2013-05-09 18:35:53 +0100471 tiling->contents_scale())
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100472 return twin_layer_->tilings_->tiling_at(i);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100473 return NULL;
474}
475
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000476gfx::Size PictureLayerImpl::CalculateTileSize(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100477 gfx::Size content_bounds) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000478 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)c2e0dbd2013-05-09 18:35:53 +0100485 int max_texture_size =
486 layer_tree_impl()->resource_provider()->max_texture_size();
487
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000488 gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100489 default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100490
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000491 gfx::Size max_untiled_content_size =
492 layer_tree_impl()->settings().max_untiled_layer_size;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100493 max_untiled_content_size.SetToMin(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100494 gfx::Size(max_texture_size, max_texture_size));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000495
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 Murdochbb1529c2013-08-08 10:24:53 +0100528void PictureLayerImpl::SyncFromActiveLayer() {
529 DCHECK(layer_tree_impl()->IsPendingTree());
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100530
Ben Murdochbb1529c2013-08-08 10:24:53 +0100531 if (twin_layer_)
532 SyncFromActiveLayer(twin_layer_);
533}
534
535void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100536 UpdateLCDTextStatus(other->is_using_lcd_text_);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100537
538 if (!DrawsContent()) {
539 ResetRasterScale();
540 return;
541 }
542
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000543 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)c2e0dbd2013-05-09 18:35:53 +0100546 raster_contents_scale_ = other->raster_contents_scale_;
547 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000548
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)2a99a7e2013-03-28 15:31:22 +0000555 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)c2e0dbd2013-05-09 18:35:53 +0100566 // 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)2a99a7e2013-03-28 15:31:22 +0000570
Ben Murdocheb525c52013-07-10 11:40:50 +0100571 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)2a99a7e2013-03-28 15:31:22 +0000584}
585
586void PictureLayerImpl::SyncTiling(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100587 const PictureLayerTiling* tiling) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100588 if (!CanHaveTilingWithScale(tiling->contents_scale()))
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000589 return;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100590 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)2a99a7e2013-03-28 15:31:22 +0000598}
599
Ben Murdochbb1529c2013-08-08 10:24:53 +0100600void 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)2a99a7e2013-03-28 15:31:22 +0000609void 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
617ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
618 gfx::Rect content_rect(content_bounds());
619 float scale = contents_scale_x();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100620 for (PictureLayerTilingSet::CoverageIterator
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000621 iter(tilings_.get(), scale, content_rect, ideal_contents_scale_);
622 iter;
623 ++iter) {
624 // Mask resource not ready yet.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100625 if (!*iter)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000626 return 0;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100627
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100628 const ManagedTileState::TileVersion& tile_version =
629 iter->GetTileVersionForDrawing();
630 if (!tile_version.IsReadyToDraw() ||
631 tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE)
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100632 return 0;
633
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000634 // Masks only supported if they fit on exactly one tile.
635 if (iter.geometry_rect() != content_rect)
636 return 0;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100637
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100638 return tile_version.get_resource_id();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000639 }
640 return 0;
641}
642
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100643void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000644 DCHECK(layer_tree_impl()->IsPendingTree());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100645 DCHECK(!layer_tree_impl()->needs_update_draw_properties());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000646 DCHECK(ideal_contents_scale_);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100647 DCHECK_GT(tilings_->num_tilings(), 0u);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000648
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100649 gfx::Rect rect(visible_content_rect());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000650
651 float min_acceptable_scale =
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100652 std::min(raster_contents_scale_, ideal_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000653
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100654 if (PictureLayerImpl* twin = twin_layer_) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100655 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)2a99a7e2013-03-28 15:31:22 +0000663 }
664
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100665 // 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)2a99a7e2013-03-28 15:31:22 +0000671 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)c2e0dbd2013-05-09 18:35:53 +0100674 DCHECK(tiling->has_ever_been_updated());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000675
676 if (tiling->contents_scale() < min_acceptable_scale)
677 continue;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100678 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)c2e0dbd2013-05-09 18:35:53 +0100683 for (PictureLayerTiling::CoverageIterator iter(tiling,
684 contents_scale_x(),
685 rect);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000686 iter;
687 ++iter) {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100688 if (!*iter || !iter->IsReadyToDraw())
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100689 continue;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100690
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)90dce4d2013-05-29 14:40:03 +0100697 missing_region.Subtract(iter.geometry_rect());
698 iter->mark_required_for_activation();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000699 }
700 }
701
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100702 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)868fa2f2013-06-11 10:57:03 +0100709 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)90dce4d2013-05-29 14:40:03 +0100718 // If the missing region doesn't cover it, this tile is fully
719 // covered by acceptable tiles at other scales.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100720 if (!missing_region.Intersects(iter.geometry_rect()))
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100721 continue;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100722
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100723 iter->mark_required_for_activation();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100724 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000725}
726
727PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100728 DCHECK(CanHaveTilingWithScale(contents_scale)) <<
729 "contents_scale: " << contents_scale;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000730
731 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
732
733 const Region& recorded = pile_->recorded_region();
734 DCHECK(!recorded.IsEmpty());
735
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100736 if (twin_layer_)
737 twin_layer_->SyncTiling(tiling);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000738
739 return tiling;
740}
741
742void 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
752namespace {
753
754inline float PositiveRatio(float float1, float float2) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100755 DCHECK_GT(float1, 0);
756 DCHECK_GT(float2, 0);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000757 return float1 > float2 ? float1 / float2 : float2 / float1;
758}
759
760inline 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
772void 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)90dce4d2013-05-29 14:40:03 +0100777 DCHECK(CanHaveTilings());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000778
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100779 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)2a99a7e2013-03-28 15:31:22 +0000786
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100787 // Store the value for the next time ShouldAdjustRasterScale is called.
788 raster_source_scale_was_animating_ = animating_transform_to_screen;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000789
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000790 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)2a99a7e2013-03-28 15:31:22 +0000797 CalculateRasterContentsScale(animating_transform_to_screen,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100798 &raster_contents_scale_,
799 &low_res_raster_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000800
801 PictureLayerTiling* high_res = NULL;
802 PictureLayerTiling* low_res = NULL;
803
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100804 PictureLayerTiling* previous_low_res = NULL;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000805 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
806 PictureLayerTiling* tiling = tilings_->tiling_at(i);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100807 if (tiling->contents_scale() == raster_contents_scale_)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000808 high_res = tiling;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100809 if (tiling->contents_scale() == low_res_raster_contents_scale_)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000810 low_res = tiling;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100811 if (tiling->resolution() == LOW_RESOLUTION)
812 previous_low_res = tiling;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000813
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)c2e0dbd2013-05-09 18:35:53 +0100819 high_res = AddTiling(raster_contents_scale_);
820 if (raster_contents_scale_ == low_res_raster_contents_scale_)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000821 low_res = high_res;
822 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100823
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)c2e0dbd2013-05-09 18:35:53 +0100830 low_res = AddTiling(low_res_raster_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000831
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)868fa2f2013-06-11 10:57:03 +0100836 else if (!low_res && previous_low_res)
837 previous_low_res->set_resolution(LOW_RESOLUTION);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000838}
839
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100840bool 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)868fa2f2013-06-11 10:57:03 +0100847 if (raster_source_scale_was_animating_ && !animating_transform_to_screen)
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100848 return true;
849
850 bool is_pinching = layer_tree_impl()->PinchGestureActive();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100851 if (is_pinching && raster_page_scale_) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100852 // 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)2a99a7e2013-03-28 15:31:22 +0000872void PictureLayerImpl::CalculateRasterContentsScale(
873 bool animating_transform_to_screen,
874 float* raster_contents_scale,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100875 float* low_res_raster_contents_scale) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000876 *raster_contents_scale = ideal_contents_scale_;
877
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100878 // Don't allow animating CSS scales to drop below 1. This is needed because
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100879 // changes in raster source scale aren't handled. See the comment in
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100880 // ShouldAdjustRasterScale.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000881 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)7d4cd472013-06-19 11:58:07 +0100886 // 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)a36e5922013-08-05 13:57:33 +0100891 if (tile_size.width() >= content_bounds.width() &&
892 tile_size.height() >= content_bounds.height()) {
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100893 *low_res_raster_contents_scale = *raster_contents_scale;
894 return;
895 }
896
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000897 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
904void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
905 std::vector<PictureLayerTiling*> used_tilings) {
906 DCHECK(layer_tree_impl()->IsActiveTree());
907
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000908 float min_acceptable_high_res_scale = std::min(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100909 raster_contents_scale_, ideal_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000910 float max_acceptable_high_res_scale = std::max(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100911 raster_contents_scale_, ideal_contents_scale_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000912
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100913 PictureLayerImpl* twin = twin_layer_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000914 if (twin) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000915 min_acceptable_high_res_scale = std::min(
916 min_acceptable_high_res_scale,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100917 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000918 max_acceptable_high_res_scale = std::max(
919 max_acceptable_high_res_scale,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100920 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000921 }
922
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000923 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)7d4cd472013-06-19 11:58:07 +0100927 // Keep multiple high resolution tilings even if not used to help
928 // activate earlier at non-ideal resolutions.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000929 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
930 tiling->contents_scale() <= max_acceptable_high_res_scale)
931 continue;
932
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100933 // Low resolution can't activate, so only keep one around.
934 if (tiling->resolution() == LOW_RESOLUTION)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000935 continue;
936
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100937 // Don't remove tilings that are being used (and thus would cause a flash.)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000938 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)2a99a7e2013-03-28 15:31:22 +0000952float 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 Murdocheb525c52013-07-10 11:40:50 +0100966void PictureLayerImpl::UpdateLCDTextStatus(bool new_status) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000967 // Once this layer is not using lcd text, don't switch back.
968 if (!is_using_lcd_text_)
969 return;
970
Ben Murdocheb525c52013-07-10 11:40:50 +0100971 if (is_using_lcd_text_ == new_status)
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000972 return;
973
Ben Murdocheb525c52013-07-10 11:40:50 +0100974 is_using_lcd_text_ = new_status;
975 tilings_->SetCanUseLCDText(is_using_lcd_text_);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100976}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000977
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100978void 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)2a99a7e2013-03-28 15:31:22 +0000984}
985
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100986bool PictureLayerImpl::CanHaveTilings() const {
987 if (!DrawsContent())
988 return false;
989 if (pile_->recorded_region().IsEmpty())
990 return false;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100991 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
997bool 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)2a99a7e2013-03-28 15:31:22 +00001005void 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)b2df76e2013-05-13 16:52:09 +01001012void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
1013 LayerImpl::AsValueInto(state);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001014 state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1015 state->Set("tilings", tilings_->AsValue().release());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001016 state->Set("pictures", pile_->AsValue().release());
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +01001017 state->Set("invalidation", invalidation_.AsValue().release());
Ben Murdochca12bfa2013-07-23 11:17:05 +01001018
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)2a99a7e2013-03-28 15:31:22 +00001035}
1036
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001037size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1038 return tilings_->GPUMemoryUsageInBytes();
1039}
1040
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001041} // namespace cc