blob: 68083c24dafe6019465669ab945cdfbb997c1e47 [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// Copyright 2011 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
[email protected]556fd292013-03-18 08:03:045#include "cc/trees/layer_tree_host_impl.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]ac7c7f52012-11-08 06:26:507#include <algorithm>
8
[email protected]ad5d1422012-10-19 13:40:299#include "base/basictypes.h"
[email protected]4456eee22012-10-19 18:16:3810#include "base/debug/trace_event.h"
[email protected]4a23c374c2012-12-08 08:38:5511#include "base/json/json_writer.h"
[email protected]f5864912013-02-01 03:18:1412#include "base/metrics/histogram.h"
[email protected]de4afb5e2012-12-20 00:11:3413#include "base/stl_util.h"
[email protected]131a0c22013-02-12 18:31:0814#include "base/stringprintf.h"
[email protected]95e4e1a02013-03-18 07:09:0915#include "cc/animation/scrollbar_animation_controller.h"
[email protected]681ccff2013-03-18 06:13:5216#include "cc/base/math_util.h"
17#include "cc/base/util.h"
[email protected]6e84de22013-03-18 06:54:2718#include "cc/debug/debug_rect_history.h"
19#include "cc/debug/frame_rate_counter.h"
20#include "cc/debug/overdraw_metrics.h"
21#include "cc/debug/paint_time_counter.h"
[email protected]372bad5f2013-03-21 16:38:4322#include "cc/debug/rendering_stats_instrumentation.h"
[email protected]3052b10f2013-03-18 07:41:2123#include "cc/input/page_scale_animation.h"
24#include "cc/input/top_controls_manager.h"
[email protected]cc3cfaa2013-03-18 09:05:5225#include "cc/layers/append_quads_data.h"
26#include "cc/layers/heads_up_display_layer_impl.h"
[email protected]50761e92013-03-29 20:51:2827#include "cc/layers/layer_impl.h"
[email protected]cc3cfaa2013-03-18 09:05:5228#include "cc/layers/layer_iterator.h"
[email protected]50761e92013-03-29 20:51:2829#include "cc/layers/render_surface_impl.h"
[email protected]cc3cfaa2013-03-18 09:05:5230#include "cc/layers/scrollbar_layer_impl.h"
[email protected]7f0d825f2013-03-18 07:24:3031#include "cc/output/compositor_frame_metadata.h"
32#include "cc/output/delegating_renderer.h"
33#include "cc/output/gl_renderer.h"
34#include "cc/output/software_renderer.h"
[email protected]89e82672013-03-18 07:50:5635#include "cc/quads/render_pass_draw_quad.h"
36#include "cc/quads/shared_quad_state.h"
37#include "cc/quads/solid_color_draw_quad.h"
[email protected]e12dd0e2013-03-18 08:24:4038#include "cc/resources/memory_history.h"
39#include "cc/resources/picture_layer_tiling.h"
40#include "cc/resources/prioritized_resource_manager.h"
[email protected]be4655a2013-03-18 08:36:3141#include "cc/scheduler/delay_based_time_source.h"
42#include "cc/scheduler/texture_uploader.h"
[email protected]556fd292013-03-18 08:03:0443#include "cc/trees/damage_tracker.h"
44#include "cc/trees/layer_tree_host.h"
45#include "cc/trees/layer_tree_host_common.h"
46#include "cc/trees/layer_tree_impl.h"
47#include "cc/trees/quad_culler.h"
48#include "cc/trees/single_thread_proxy.h"
49#include "cc/trees/tree_synchronizer.h"
[email protected]d455d552012-11-02 00:19:0650#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1351#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1452
[email protected]94f206c12012-08-25 00:09:1453namespace {
54
[email protected]c1bb5af2013-03-13 19:06:2755void DidVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) {
56 if (visible) {
57 TRACE_EVENT_ASYNC_BEGIN1("webkit",
58 "LayerTreeHostImpl::SetVisible",
59 id,
60 "LayerTreeHostImpl",
61 id);
62 return;
63 }
[email protected]94f206c12012-08-25 00:09:1464
[email protected]c1bb5af2013-03-13 19:06:2765 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::SetVisible", id);
[email protected]94f206c12012-08-25 00:09:1466}
67
[email protected]c1bb5af2013-03-13 19:06:2768std::string ValueToString(scoped_ptr<base::Value> value) {
69 std::string str;
70 base::JSONWriter::Write(value.get(), &str);
71 return str;
[email protected]131a0c22013-02-12 18:31:0872}
73
[email protected]c1bb5af2013-03-13 19:06:2774} // namespace
[email protected]94f206c12012-08-25 00:09:1475
[email protected]9c88e562012-09-14 22:21:3076namespace cc {
[email protected]94f206c12012-08-25 00:09:1477
[email protected]96baf3e2012-10-22 23:09:5578class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]c1bb5af2013-03-13 19:06:2779 public:
80 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create(
81 LayerTreeHostImpl* layer_tree_host_impl,
82 scoped_refptr<DelayBasedTimeSource> time_source) {
83 return make_scoped_ptr(
84 new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl,
85 time_source));
86 }
87 virtual ~LayerTreeHostImplTimeSourceAdapter() {
[email protected]6d0e69d2013-03-20 14:53:2688 time_source_->SetClient(NULL);
89 time_source_->SetActive(false);
[email protected]c1bb5af2013-03-13 19:06:2790 }
91
[email protected]6d0e69d2013-03-20 14:53:2692 virtual void OnTimerTick() OVERRIDE {
[email protected]c1bb5af2013-03-13 19:06:2793 // In single threaded mode we attempt to simulate changing the current
94 // thread by maintaining a fake thread id. When we switch from one
95 // thread to another, we construct DebugScopedSetXXXThread objects that
96 // update the thread id. This lets DCHECKS that ensure we're on the
97 // right thread to work correctly in single threaded mode. The problem
98 // here is that the timer tasks are run via the message loop, and when
99 // they run, we've had no chance to construct a DebugScopedSetXXXThread
100 // object. The result is that we report that we're running on the main
101 // thread. In multi-threaded mode, this timer is run on the compositor
102 // thread, so to keep this consistent in single-threaded mode, we'll
103 // construct a DebugScopedSetImplThread object. There is no need to do
104 // this in multi-threaded mode since the real thread id's will be
105 // correct. In fact, setting fake thread id's interferes with the real
106 // thread id's and causes breakage.
107 scoped_ptr<DebugScopedSetImplThread> set_impl_thread;
108 if (!layer_tree_host_impl_->proxy()->HasImplThread()) {
109 set_impl_thread.reset(
110 new DebugScopedSetImplThread(layer_tree_host_impl_->proxy()));
[email protected]94f206c12012-08-25 00:09:14111 }
112
[email protected]c1bb5af2013-03-13 19:06:27113 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
114 layer_tree_host_impl_->Animate(base::TimeTicks::Now(), base::Time::Now());
[email protected]3d9f7432013-04-06 00:35:18115 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(true);
116 bool start_ready_animations = true;
117 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
[email protected]c1bb5af2013-03-13 19:06:27118 layer_tree_host_impl_->BeginNextFrame();
119 }
[email protected]373974232013-01-10 22:20:50120
[email protected]c1bb5af2013-03-13 19:06:27121 void SetActive(bool active) {
[email protected]6d0e69d2013-03-20 14:53:26122 if (active != time_source_->Active())
123 time_source_->SetActive(active);
[email protected]c1bb5af2013-03-13 19:06:27124 }
[email protected]94f206c12012-08-25 00:09:14125
[email protected]c1bb5af2013-03-13 19:06:27126 private:
127 LayerTreeHostImplTimeSourceAdapter(
128 LayerTreeHostImpl* layer_tree_host_impl,
129 scoped_refptr<DelayBasedTimeSource> time_source)
130 : layer_tree_host_impl_(layer_tree_host_impl),
131 time_source_(time_source) {
[email protected]6d0e69d2013-03-20 14:53:26132 time_source_->SetClient(this);
[email protected]c1bb5af2013-03-13 19:06:27133 }
[email protected]94f206c12012-08-25 00:09:14134
[email protected]c1bb5af2013-03-13 19:06:27135 LayerTreeHostImpl* layer_tree_host_impl_;
136 scoped_refptr<DelayBasedTimeSource> time_source_;
[email protected]94f206c12012-08-25 00:09:14137
[email protected]c1bb5af2013-03-13 19:06:27138 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14139};
140
[email protected]96baf3e2012-10-22 23:09:55141LayerTreeHostImpl::FrameData::FrameData()
[email protected]c1bb5af2013-03-13 19:06:27142 : contains_incomplete_tile(false) {}
143
144LayerTreeHostImpl::FrameData::~FrameData() {}
145
146scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
147 const LayerTreeSettings& settings,
148 LayerTreeHostImplClient* client,
[email protected]372bad5f2013-03-21 16:38:43149 Proxy* proxy,
150 RenderingStatsInstrumentation* rendering_stats_instrumentation) {
151 return make_scoped_ptr(
152 new LayerTreeHostImpl(settings,
153 client,
154 proxy,
155 rendering_stats_instrumentation));
[email protected]493067512012-09-19 23:34:10156}
157
[email protected]372bad5f2013-03-21 16:38:43158LayerTreeHostImpl::LayerTreeHostImpl(
159 const LayerTreeSettings& settings,
160 LayerTreeHostImplClient* client,
161 Proxy* proxy,
162 RenderingStatsInstrumentation* rendering_stats_instrumentation)
[email protected]c1bb5af2013-03-13 19:06:27163 : client_(client),
164 proxy_(proxy),
165 did_lock_scrolling_layer_(false),
166 should_bubble_scrolls_(false),
167 wheel_scrolling_(false),
168 settings_(settings),
[email protected]d9083762013-03-24 01:36:40169 overdraw_bottom_height_(0.f),
[email protected]c1bb5af2013-03-13 19:06:27170 device_scale_factor_(1.f),
171 visible_(true),
172 managed_memory_policy_(
[email protected]b56c1302013-03-20 21:17:34173 PrioritizedResourceManager::DefaultMemoryAllocationLimit(),
[email protected]c1bb5af2013-03-13 19:06:27174 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
175 0,
176 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING),
177 pinch_gesture_active_(false),
[email protected]9e3594522013-03-18 00:57:36178 fps_counter_(FrameRateCounter::Create(proxy_->HasImplThread())),
[email protected]7497316a2013-03-15 12:42:29179 paint_time_counter_(PaintTimeCounter::Create()),
[email protected]c1bb5af2013-03-13 19:06:27180 memory_history_(MemoryHistory::Create()),
[email protected]d35992782013-03-14 14:54:02181 debug_rect_history_(DebugRectHistory::Create()),
[email protected]d7626ffd2013-03-29 00:17:42182 max_memory_needed_bytes_(0),
[email protected]c1bb5af2013-03-13 19:06:27183 last_sent_memory_visible_bytes_(0),
184 last_sent_memory_visible_and_nearby_bytes_(0),
185 last_sent_memory_use_bytes_(0),
[email protected]372bad5f2013-03-21 16:38:43186 animation_registrar_(AnimationRegistrar::Create()),
187 rendering_stats_instrumentation_(rendering_stats_instrumentation) {
[email protected]c1bb5af2013-03-13 19:06:27188 DCHECK(proxy_->IsImplThread());
189 DidVisibilityChange(this, visible_);
190
[email protected]8e0176d2013-03-21 03:14:52191 SetDebugState(settings.initial_debug_state);
[email protected]c1bb5af2013-03-13 19:06:27192
[email protected]8e0176d2013-03-21 03:14:52193 if (settings.calculate_top_controls_position) {
[email protected]c1bb5af2013-03-13 19:06:27194 top_controls_manager_ =
195 TopControlsManager::Create(this,
[email protected]8e0176d2013-03-21 03:14:52196 settings.top_controls_height,
197 settings.top_controls_show_threshold,
198 settings.top_controls_hide_threshold);
[email protected]c1bb5af2013-03-13 19:06:27199 }
200
[email protected]8e0176d2013-03-21 03:14:52201 SetDebugState(settings.initial_debug_state);
[email protected]c1bb5af2013-03-13 19:06:27202
203 // LTHI always has an active tree.
204 active_tree_ = LayerTreeImpl::create(this);
[email protected]493067512012-09-19 23:34:10205}
206
[email protected]c1bb5af2013-03-13 19:06:27207LayerTreeHostImpl::~LayerTreeHostImpl() {
208 DCHECK(proxy_->IsImplThread());
209 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
210
211 if (active_tree_->root_layer()) {
212 ClearRenderSurfaces();
213 // The layer trees must be destroyed before the layer tree host. We've
214 // made a contract with our animation controllers that the registrar
215 // will outlive them, and we must make good.
216 recycle_tree_.reset();
217 pending_tree_.reset();
218 active_tree_.reset();
219 }
[email protected]94f206c12012-08-25 00:09:14220}
221
[email protected]c1bb5af2013-03-13 19:06:27222void LayerTreeHostImpl::BeginCommit() {}
[email protected]3b31c6ac2012-12-06 21:27:29223
[email protected]c1bb5af2013-03-13 19:06:27224void LayerTreeHostImpl::CommitComplete() {
225 TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete");
[email protected]131a0c22013-02-12 18:31:08226
[email protected]c1bb5af2013-03-13 19:06:27227 // Impl-side painting needs an update immediately post-commit to have the
228 // opportunity to create tilings. Other paths can call UpdateDrawProperties
229 // more lazily when needed prior to drawing.
[email protected]8e0176d2013-03-21 03:14:52230 if (settings_.impl_side_painting) {
[email protected]c1bb5af2013-03-13 19:06:27231 pending_tree_->set_needs_update_draw_properties();
232 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE);
233 } else {
234 active_tree_->set_needs_update_draw_properties();
235 }
[email protected]3ba4cae2013-01-16 03:58:38236
[email protected]c1bb5af2013-03-13 19:06:27237 client_->SendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14238}
239
[email protected]c1bb5af2013-03-13 19:06:27240bool LayerTreeHostImpl::CanDraw() {
241 // Note: If you are changing this function or any other function that might
242 // affect the result of CanDraw, make sure to call
243 // client_->OnCanDrawStateChanged in the proper places and update the
244 // NotifyIfCanDrawChanged test.
[email protected]94f206c12012-08-25 00:09:14245
[email protected]c1bb5af2013-03-13 19:06:27246 if (!active_tree_->root_layer()) {
[email protected]c76faea2013-03-26 07:42:42247 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no root layer",
248 TRACE_EVENT_SCOPE_THREAD);
[email protected]2f1acc262012-11-16 21:42:22249 return false;
[email protected]c1bb5af2013-03-13 19:06:27250 }
251 if (device_viewport_size_.IsEmpty()) {
[email protected]c76faea2013-03-26 07:42:42252 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport",
253 TRACE_EVENT_SCOPE_THREAD);
[email protected]c1bb5af2013-03-13 19:06:27254 return false;
255 }
256 if (active_tree_->ViewportSizeInvalid()) {
257 TRACE_EVENT_INSTANT0(
[email protected]c76faea2013-03-26 07:42:42258 "cc", "LayerTreeHostImpl::CanDraw viewport size recently changed",
259 TRACE_EVENT_SCOPE_THREAD);
[email protected]c1bb5af2013-03-13 19:06:27260 return false;
261 }
262 if (!renderer_) {
[email protected]c76faea2013-03-26 07:42:42263 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no renderer",
264 TRACE_EVENT_SCOPE_THREAD);
[email protected]c1bb5af2013-03-13 19:06:27265 return false;
266 }
267 if (active_tree_->ContentsTexturesPurged()) {
268 TRACE_EVENT_INSTANT0(
[email protected]c76faea2013-03-26 07:42:42269 "cc", "LayerTreeHostImpl::CanDraw contents textures purged",
270 TRACE_EVENT_SCOPE_THREAD);
[email protected]c1bb5af2013-03-13 19:06:27271 return false;
272 }
273 return true;
[email protected]2f1acc262012-11-16 21:42:22274}
275
[email protected]c1bb5af2013-03-13 19:06:27276void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time,
277 base::Time wall_clock_time) {
278 AnimatePageScale(monotonic_time);
279 AnimateLayers(monotonic_time, wall_clock_time);
280 AnimateScrollbars(monotonic_time);
[email protected]ffb2720f2013-03-15 19:18:37281 AnimateTopControls(monotonic_time);
[email protected]94f206c12012-08-25 00:09:14282}
283
[email protected]c1bb5af2013-03-13 19:06:27284void LayerTreeHostImpl::ManageTiles() {
285 DCHECK(tile_manager_);
286 tile_manager_->ManageTiles();
287
288 size_t memory_required_bytes;
289 size_t memory_nice_to_have_bytes;
290 size_t memory_used_bytes;
291 tile_manager_->GetMemoryStats(&memory_required_bytes,
292 &memory_nice_to_have_bytes,
293 &memory_used_bytes);
294 SendManagedMemoryStats(memory_required_bytes,
295 memory_nice_to_have_bytes,
296 memory_used_bytes);
[email protected]f57bbc02012-11-21 07:02:15297}
298
[email protected]80334ba2013-03-20 17:33:50299void LayerTreeHostImpl::SetAnticipatedDrawTime(base::TimeTicks time) {
[email protected]f8456612013-03-19 20:56:09300 if (tile_manager_)
301 tile_manager_->SetAnticipatedDrawTime(time);
302}
303
[email protected]c1bb5af2013-03-13 19:06:27304void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset,
305 bool anchor_point,
306 float page_scale,
307 base::TimeTicks start_time,
308 base::TimeDelta duration) {
309 if (!RootScrollLayer())
310 return;
311
312 gfx::Vector2dF scroll_total =
313 RootScrollLayer()->scroll_offset() + RootScrollLayer()->scroll_delta();
314 gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
[email protected]6fc4ee002013-03-26 23:39:51315 gfx::SizeF viewport_size = VisibleViewportSize();
[email protected]c1bb5af2013-03-13 19:06:27316
317 double start_time_seconds = (start_time - base::TimeTicks()).InSecondsF();
318 page_scale_animation_ =
319 PageScaleAnimation::Create(scroll_total,
320 active_tree_->total_page_scale_factor(),
321 viewport_size,
322 scaled_scrollable_size,
323 start_time_seconds);
324
325 if (anchor_point) {
326 gfx::Vector2dF anchor(target_offset);
327 page_scale_animation_->ZoomWithAnchor(anchor,
328 page_scale,
329 duration.InSecondsF());
330 } else {
331 gfx::Vector2dF scaled_target_offset = target_offset;
332 page_scale_animation_->ZoomTo(scaled_target_offset,
333 page_scale,
334 duration.InSecondsF());
335 }
336
337 client_->SetNeedsRedrawOnImplThread();
338 client_->SetNeedsCommitOnImplThread();
339 client_->RenewTreePriority();
[email protected]f57bbc02012-11-21 07:02:15340}
341
[email protected]c1bb5af2013-03-13 19:06:27342void LayerTreeHostImpl::ScheduleAnimation() {
343 client_->SetNeedsRedrawOnImplThread();
[email protected]f57bbc02012-11-21 07:02:15344}
345
[email protected]c1bb5af2013-03-13 19:06:27346bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) {
347 if (!EnsureRenderSurfaceLayerList())
348 return false;
[email protected]f57bbc02012-11-21 07:02:15349
[email protected]c1bb5af2013-03-13 19:06:27350 gfx::PointF device_viewport_point =
351 gfx::ScalePoint(viewport_point, device_scale_factor_);
[email protected]f57bbc02012-11-21 07:02:15352
[email protected]c1bb5af2013-03-13 19:06:27353 // First find out which layer was hit from the saved list of visible layers
354 // in the most recent frame.
[email protected]6ba914122013-03-22 16:26:39355 LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
[email protected]c1bb5af2013-03-13 19:06:27356 device_viewport_point,
357 active_tree_->RenderSurfaceLayerList());
[email protected]f57bbc02012-11-21 07:02:15358
[email protected]c1bb5af2013-03-13 19:06:27359 // Walk up the hierarchy and look for a layer with a touch event handler
360 // region that the given point hits.
361 for (; layer_impl; layer_impl = layer_impl->parent()) {
[email protected]6ba914122013-03-22 16:26:39362 if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(device_viewport_point,
[email protected]c1bb5af2013-03-13 19:06:27363 layer_impl))
364 return true;
365 }
[email protected]f57bbc02012-11-21 07:02:15366
[email protected]c1bb5af2013-03-13 19:06:27367 return false;
368}
369
370void LayerTreeHostImpl::TrackDamageForAllSurfaces(
371 LayerImpl* root_draw_layer,
[email protected]50761e92013-03-29 20:51:28372 const LayerImplList& render_surface_layer_list) {
[email protected]c1bb5af2013-03-13 19:06:27373 // For now, we use damage tracking to compute a global scissor. To do this, we
374 // must compute all damage tracking before drawing anything, so that we know
375 // the root damage rect. The root damage rect is then used to scissor each
376 // surface.
377
378 for (int surface_index = render_surface_layer_list.size() - 1;
[email protected]bf691c22013-03-26 21:15:06379 surface_index >= 0;
[email protected]c1bb5af2013-03-13 19:06:27380 --surface_index) {
381 LayerImpl* render_surface_layer = render_surface_layer_list[surface_index];
382 RenderSurfaceImpl* render_surface = render_surface_layer->render_surface();
383 DCHECK(render_surface);
384 render_surface->damage_tracker()->UpdateDamageTrackingState(
385 render_surface->layer_list(),
386 render_surface_layer->id(),
387 render_surface->SurfacePropertyChangedOnlyFromDescendant(),
388 render_surface->content_rect(),
389 render_surface_layer->mask_layer(),
390 render_surface_layer->filters(),
391 render_surface_layer->filter().get());
392 }
393}
394
395void LayerTreeHostImpl::FrameData::AppendRenderPass(
396 scoped_ptr<RenderPass> render_pass) {
397 render_passes_by_id[render_pass->id] = render_pass.get();
398 render_passes.push_back(render_pass.Pass());
399}
400
401static void AppendQuadsForLayer(RenderPass* target_render_pass,
402 LayerImpl* layer,
403 const OcclusionTrackerImpl& occlusion_tracker,
404 AppendQuadsData* append_quads_data) {
405 bool for_surface = false;
[email protected]c7e95b42013-03-18 01:13:49406 QuadCuller quad_culler(&target_render_pass->quad_list,
407 &target_render_pass->shared_quad_state_list,
[email protected]c1bb5af2013-03-13 19:06:27408 layer,
409 occlusion_tracker,
410 layer->ShowDebugBorders(),
411 for_surface);
412 layer->AppendQuads(&quad_culler, append_quads_data);
413}
414
415static void AppendQuadsForRenderSurfaceLayer(
416 RenderPass* target_render_pass,
417 LayerImpl* layer,
418 const RenderPass* contributing_render_pass,
419 const OcclusionTrackerImpl& occlusion_tracker,
420 AppendQuadsData* append_quads_data) {
421 bool for_surface = true;
[email protected]c7e95b42013-03-18 01:13:49422 QuadCuller quad_culler(&target_render_pass->quad_list,
423 &target_render_pass->shared_quad_state_list,
[email protected]c1bb5af2013-03-13 19:06:27424 layer,
425 occlusion_tracker,
426 layer->ShowDebugBorders(),
427 for_surface);
428
429 bool is_replica = false;
430 layer->render_surface()->AppendQuads(&quad_culler,
431 append_quads_data,
432 is_replica,
433 contributing_render_pass->id);
434
435 // Add replica after the surface so that it appears below the surface.
436 if (layer->has_replica()) {
437 is_replica = true;
438 layer->render_surface()->AppendQuads(&quad_culler,
439 append_quads_data,
440 is_replica,
441 contributing_render_pass->id);
442 }
443}
444
445static void AppendQuadsToFillScreen(
446 RenderPass* target_render_pass,
447 LayerImpl* root_layer,
448 SkColor screen_background_color,
449 const OcclusionTrackerImpl& occlusion_tracker) {
450 if (!root_layer || !SkColorGetA(screen_background_color))
451 return;
452
453 Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen();
454 if (fill_region.IsEmpty())
455 return;
456
457 bool for_surface = false;
[email protected]c7e95b42013-03-18 01:13:49458 QuadCuller quad_culler(&target_render_pass->quad_list,
459 &target_render_pass->shared_quad_state_list,
[email protected]c1bb5af2013-03-13 19:06:27460 root_layer,
461 occlusion_tracker,
462 root_layer->ShowDebugBorders(),
463 for_surface);
464
465 // Manually create the quad state for the gutter quads, as the root layer
466 // doesn't have any bounds and so can't generate this itself.
467 // TODO(danakj): Make the gutter quads generated by the solid color layer
468 // (make it smarter about generating quads to fill unoccluded areas).
469
470 gfx::Rect root_target_rect = root_layer->render_surface()->content_rect();
471 float opacity = 1.f;
472 SharedQuadState* shared_quad_state =
[email protected]c7e95b42013-03-18 01:13:49473 quad_culler.UseSharedQuadState(SharedQuadState::Create());
[email protected]c1bb5af2013-03-13 19:06:27474 shared_quad_state->SetAll(root_layer->draw_transform(),
475 root_target_rect.size(),
476 root_target_rect,
477 root_target_rect,
[email protected]dc462d782012-11-21 21:43:01478 false,
[email protected]f57bbc02012-11-21 07:02:15479 opacity);
480
[email protected]c1bb5af2013-03-13 19:06:27481 AppendQuadsData append_quads_data;
[email protected]bda41962013-01-07 18:46:17482
[email protected]c1bb5af2013-03-13 19:06:27483 gfx::Transform transform_to_layer_space(gfx::Transform::kSkipInitialization);
484 bool did_invert = root_layer->screen_space_transform().GetInverse(
485 &transform_to_layer_space);
486 DCHECK(did_invert);
487 for (Region::Iterator fill_rects(fill_region);
488 fill_rects.has_rect();
489 fill_rects.next()) {
490 // The root layer transform is composed of translations and scales only,
491 // no perspective, so mapping is sufficient (as opposed to projecting).
492 gfx::Rect layer_rect =
[email protected]fa816c62013-03-18 04:24:21493 MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect());
[email protected]c1bb5af2013-03-13 19:06:27494 // Skip the quad culler and just append the quads directly to avoid
495 // occlusion checks.
496 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
497 quad->SetNew(shared_quad_state, layer_rect, screen_background_color);
[email protected]c7e95b42013-03-18 01:13:49498 quad_culler.Append(quad.PassAs<DrawQuad>(), &append_quads_data);
[email protected]c1bb5af2013-03-13 19:06:27499 }
[email protected]467b3612012-08-28 07:41:16500}
501
[email protected]c1bb5af2013-03-13 19:06:27502bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
503 DCHECK(frame->render_passes.empty());
[email protected]94f206c12012-08-25 00:09:14504
[email protected]c1bb5af2013-03-13 19:06:27505 if (!CanDraw() || !active_tree_->root_layer())
506 return false;
[email protected]2d692992012-12-19 01:19:32507
[email protected]c1bb5af2013-03-13 19:06:27508 TrackDamageForAllSurfaces(active_tree_->root_layer(),
509 *frame->render_surface_layer_list);
[email protected]94f206c12012-08-25 00:09:14510
[email protected]c1bb5af2013-03-13 19:06:27511 TRACE_EVENT1("cc",
512 "LayerTreeHostImpl::CalculateRenderPasses",
513 "render_surface_layer_list.size()",
[email protected]bf691c22013-03-26 21:15:06514 static_cast<uint64>(frame->render_surface_layer_list->size()));
[email protected]94f206c12012-08-25 00:09:14515
[email protected]c1bb5af2013-03-13 19:06:27516 // Create the render passes in dependency order.
517 for (int surface_index = frame->render_surface_layer_list->size() - 1;
[email protected]bf691c22013-03-26 21:15:06518 surface_index >= 0;
[email protected]c1bb5af2013-03-13 19:06:27519 --surface_index) {
520 LayerImpl* render_surface_layer =
521 (*frame->render_surface_layer_list)[surface_index];
522 render_surface_layer->render_surface()->AppendRenderPasses(frame);
523 }
[email protected]94f206c12012-08-25 00:09:14524
[email protected]c1bb5af2013-03-13 19:06:27525 bool record_metrics_for_frame =
[email protected]8e0176d2013-03-21 03:14:52526 settings_.show_overdraw_in_tracing &&
[email protected]c1bb5af2013-03-13 19:06:27527 base::debug::TraceLog::GetInstance() &&
528 base::debug::TraceLog::GetInstance()->IsEnabled();
529 OcclusionTrackerImpl occlusion_tracker(
530 active_tree_->root_layer()->render_surface()->content_rect(),
531 record_metrics_for_frame);
532 occlusion_tracker.set_minimum_tracking_size(
[email protected]8e0176d2013-03-21 03:14:52533 settings_.minimum_occlusion_tracking_size);
[email protected]94f206c12012-08-25 00:09:14534
[email protected]846f455b2013-03-18 19:07:41535 if (debug_state_.show_occluding_rects) {
[email protected]c1bb5af2013-03-13 19:06:27536 occlusion_tracker.set_occluding_screen_space_rects_container(
537 &frame->occluding_screen_space_rects);
538 }
[email protected]846f455b2013-03-18 19:07:41539 if (debug_state_.show_non_occluding_rects) {
[email protected]c1bb5af2013-03-13 19:06:27540 occlusion_tracker.set_non_occluding_screen_space_rects_container(
541 &frame->non_occluding_screen_space_rects);
542 }
[email protected]94f206c12012-08-25 00:09:14543
[email protected]c1bb5af2013-03-13 19:06:27544 // Add quads to the Render passes in FrontToBack order to allow for testing
545 // occlusion and performing culling during the tree walk.
546 typedef LayerIterator<LayerImpl,
[email protected]50761e92013-03-29 20:51:28547 LayerImplList,
[email protected]c1bb5af2013-03-13 19:06:27548 RenderSurfaceImpl,
549 LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14550
[email protected]c1bb5af2013-03-13 19:06:27551 // Typically when we are missing a texture and use a checkerboard quad, we
552 // still draw the frame. However when the layer being checkerboarded is moving
553 // due to an impl-animation, we drop the frame to avoid flashing due to the
554 // texture suddenly appearing in the future.
555 bool draw_frame = true;
[email protected]94f206c12012-08-25 00:09:14556
[email protected]372bad5f2013-03-21 16:38:43557 int layers_drawn = 0;
558
[email protected]c1bb5af2013-03-13 19:06:27559 LayerIteratorType end =
[email protected]71dfcc72013-03-20 21:30:09560 LayerIteratorType::End(frame->render_surface_layer_list);
[email protected]c1bb5af2013-03-13 19:06:27561 for (LayerIteratorType it =
[email protected]71dfcc72013-03-20 21:30:09562 LayerIteratorType::Begin(frame->render_surface_layer_list);
[email protected]c1bb5af2013-03-13 19:06:27563 it != end;
564 ++it) {
565 RenderPass::Id target_render_pass_id =
[email protected]71dfcc72013-03-20 21:30:09566 it.target_render_surface_layer()->render_surface()->RenderPassId();
[email protected]c1bb5af2013-03-13 19:06:27567 RenderPass* target_render_pass =
568 frame->render_passes_by_id[target_render_pass_id];
[email protected]94f206c12012-08-25 00:09:14569
[email protected]c1bb5af2013-03-13 19:06:27570 occlusion_tracker.EnterLayer(it);
[email protected]94f206c12012-08-25 00:09:14571
[email protected]c1bb5af2013-03-13 19:06:27572 AppendQuadsData append_quads_data(target_render_pass->id);
[email protected]89228202012-08-29 03:20:30573
[email protected]71dfcc72013-03-20 21:30:09574 if (it.represents_contributing_render_surface()) {
[email protected]c1bb5af2013-03-13 19:06:27575 RenderPass::Id contributing_render_pass_id =
576 it->render_surface()->RenderPassId();
577 RenderPass* contributing_render_pass =
578 frame->render_passes_by_id[contributing_render_pass_id];
579 AppendQuadsForRenderSurfaceLayer(target_render_pass,
580 *it,
581 contributing_render_pass,
582 occlusion_tracker,
583 &append_quads_data);
[email protected]e1e768f2013-03-26 08:48:09584 } else if (it.represents_itself() &&
585 !it->visible_content_rect().IsEmpty()) {
[email protected]c1bb5af2013-03-13 19:06:27586 bool has_occlusion_from_outside_target_surface;
587 bool impl_draw_transform_is_unknown = false;
588 if (occlusion_tracker.Occluded(
589 it->render_target(),
590 it->visible_content_rect(),
591 it->draw_transform(),
592 impl_draw_transform_is_unknown,
593 it->is_clipped(),
594 it->clip_rect(),
595 &has_occlusion_from_outside_target_surface)) {
[email protected]e1e768f2013-03-26 08:48:09596 append_quads_data.had_occlusion_from_outside_target_surface |=
[email protected]c1bb5af2013-03-13 19:06:27597 has_occlusion_from_outside_target_surface;
598 } else {
599 DCHECK_EQ(active_tree_, it->layer_tree_impl());
600 it->WillDraw(resource_provider_.get());
601 frame->will_draw_layers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57602
[email protected]c1bb5af2013-03-13 19:06:27603 if (it->HasContributingDelegatedRenderPasses()) {
604 RenderPass::Id contributing_render_pass_id =
605 it->FirstContributingRenderPassId();
606 while (frame->render_passes_by_id.find(contributing_render_pass_id) !=
607 frame->render_passes_by_id.end()) {
608 RenderPass* render_pass =
609 frame->render_passes_by_id[contributing_render_pass_id];
[email protected]f5864912013-02-01 03:18:14610
[email protected]c1bb5af2013-03-13 19:06:27611 AppendQuadsData append_quads_data(render_pass->id);
612 AppendQuadsForLayer(render_pass,
613 *it,
614 occlusion_tracker,
615 &append_quads_data);
[email protected]7d929c02012-09-20 17:26:57616
[email protected]c1bb5af2013-03-13 19:06:27617 contributing_render_pass_id =
618 it->NextContributingRenderPassId(contributing_render_pass_id);
619 }
[email protected]94f206c12012-08-25 00:09:14620 }
621
[email protected]c1bb5af2013-03-13 19:06:27622 AppendQuadsForLayer(target_render_pass,
623 *it,
624 occlusion_tracker,
625 &append_quads_data);
626 }
[email protected]89228202012-08-29 03:20:30627
[email protected]372bad5f2013-03-21 16:38:43628 ++layers_drawn;
[email protected]94f206c12012-08-25 00:09:14629 }
630
[email protected]e1e768f2013-03-26 08:48:09631 if (append_quads_data.had_occlusion_from_outside_target_surface)
[email protected]c1bb5af2013-03-13 19:06:27632 target_render_pass->has_occlusion_from_outside_target_surface = true;
633
[email protected]e1e768f2013-03-26 08:48:09634 if (append_quads_data.num_missing_tiles) {
[email protected]372bad5f2013-03-21 16:38:43635 rendering_stats_instrumentation_->AddMissingTiles(
[email protected]e1e768f2013-03-26 08:48:09636 append_quads_data.num_missing_tiles);
[email protected]c1bb5af2013-03-13 19:06:27637 bool layer_has_animating_transform =
638 it->screen_space_transform_is_animating() ||
639 it->draw_transform_is_animating();
640 if (layer_has_animating_transform)
641 draw_frame = false;
642 }
643
[email protected]e1e768f2013-03-26 08:48:09644 if (append_quads_data.had_incomplete_tile)
[email protected]c1bb5af2013-03-13 19:06:27645 frame->contains_incomplete_tile = true;
646
647 occlusion_tracker.LeaveLayer(it);
648 }
649
[email protected]372bad5f2013-03-21 16:38:43650 rendering_stats_instrumentation_->AddLayersDrawn(layers_drawn);
651
[email protected]1d993172012-10-18 18:15:04652#ifndef NDEBUG
[email protected]c1bb5af2013-03-13 19:06:27653 for (size_t i = 0; i < frame->render_passes.size(); ++i) {
654 for (size_t j = 0; j < frame->render_passes[i]->quad_list.size(); ++j)
655 DCHECK(frame->render_passes[i]->quad_list[j]->shared_quad_state);
656 DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id)
657 != frame->render_passes_by_id.end());
658 }
[email protected]94f206c12012-08-25 00:09:14659#endif
[email protected]c1bb5af2013-03-13 19:06:27660 DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin());
[email protected]94f206c12012-08-25 00:09:14661
[email protected]c1bb5af2013-03-13 19:06:27662 if (!active_tree_->has_transparent_background()) {
663 frame->render_passes.back()->has_transparent_background = false;
664 AppendQuadsToFillScreen(frame->render_passes.back(),
665 active_tree_->root_layer(),
666 active_tree_->background_color(),
667 occlusion_tracker);
668 }
[email protected]94f206c12012-08-25 00:09:14669
[email protected]c1bb5af2013-03-13 19:06:27670 if (draw_frame)
671 occlusion_tracker.overdraw_metrics()->RecordMetrics(this);
[email protected]94f206c12012-08-25 00:09:14672
[email protected]c1bb5af2013-03-13 19:06:27673 RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame);
674 renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes);
[email protected]bf691c22013-03-26 21:15:06675 RemoveRenderPasses(CullRenderPassesWithCachedTextures(renderer_.get()),
676 frame);
[email protected]94f206c12012-08-25 00:09:14677
[email protected]c1bb5af2013-03-13 19:06:27678 return draw_frame;
[email protected]94f206c12012-08-25 00:09:14679}
680
[email protected]3d9f7432013-04-06 00:35:18681void LayerTreeHostImpl::UpdateBackgroundAnimateTicking(
682 bool should_background_tick) {
683 bool enabled = should_background_tick &&
684 !animation_registrar_->active_animation_controllers().empty();
685
[email protected]c1bb5af2013-03-13 19:06:27686 // Lazily create the time_source adapter so that we can vary the interval for
687 // testing.
688 if (!time_source_client_adapter_) {
689 time_source_client_adapter_ = LayerTreeHostImplTimeSourceAdapter::Create(
690 this,
[email protected]6d0e69d2013-03-20 14:53:26691 DelayBasedTimeSource::Create(LowFrequencyAnimationInterval(),
[email protected]c1bb5af2013-03-13 19:06:27692 proxy_->CurrentThread()));
693 }
[email protected]94f206c12012-08-25 00:09:14694
[email protected]c1bb5af2013-03-13 19:06:27695 time_source_client_adapter_->SetActive(enabled);
[email protected]94f206c12012-08-25 00:09:14696}
697
[email protected]c1bb5af2013-03-13 19:06:27698static inline RenderPass* FindRenderPassById(
699 RenderPass::Id render_pass_id,
700 const LayerTreeHostImpl::FrameData& frame) {
701 RenderPassIdHashMap::const_iterator it =
702 frame.render_passes_by_id.find(render_pass_id);
703 return it != frame.render_passes_by_id.end() ? it->second : NULL;
[email protected]94f206c12012-08-25 00:09:14704}
705
[email protected]c1bb5af2013-03-13 19:06:27706static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id,
707 LayerTreeHostImpl::FrameData* frame) {
708 RenderPass* remove_render_pass =
709 FindRenderPassById(remove_render_pass_id, *frame);
710 // The pass was already removed by another quad - probably the original, and
711 // we are the replica.
712 if (!remove_render_pass)
713 return;
714 RenderPassList& render_passes = frame->render_passes;
715 RenderPassList::iterator to_remove = std::find(render_passes.begin(),
716 render_passes.end(),
717 remove_render_pass);
[email protected]94f206c12012-08-25 00:09:14718
[email protected]c1bb5af2013-03-13 19:06:27719 DCHECK(to_remove != render_passes.end());
[email protected]94f206c12012-08-25 00:09:14720
[email protected]c1bb5af2013-03-13 19:06:27721 scoped_ptr<RenderPass> removed_pass = render_passes.take(to_remove);
722 frame->render_passes.erase(to_remove);
723 frame->render_passes_by_id.erase(remove_render_pass_id);
[email protected]94f206c12012-08-25 00:09:14724
[email protected]c1bb5af2013-03-13 19:06:27725 // Now follow up for all RenderPass quads and remove their RenderPasses
726 // recursively.
727 const QuadList& quad_list = removed_pass->quad_list;
[email protected]ed511b8d2013-03-25 03:29:29728 QuadList::ConstBackToFrontIterator quad_list_iterator =
729 quad_list.BackToFrontBegin();
730 for (; quad_list_iterator != quad_list.BackToFrontEnd();
[email protected]c1bb5af2013-03-13 19:06:27731 ++quad_list_iterator) {
732 DrawQuad* current_quad = (*quad_list_iterator);
733 if (current_quad->material != DrawQuad::RENDER_PASS)
734 continue;
[email protected]94f206c12012-08-25 00:09:14735
[email protected]c1bb5af2013-03-13 19:06:27736 RenderPass::Id next_remove_render_pass_id =
737 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id;
738 RemoveRenderPassesRecursive(next_remove_render_pass_id, frame);
739 }
[email protected]94f206c12012-08-25 00:09:14740}
741
[email protected]c1bb5af2013-03-13 19:06:27742bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::
743 ShouldRemoveRenderPass(const RenderPassDrawQuad& quad,
744 const FrameData& frame) const {
745 bool quad_has_damage = !quad.contents_changed_since_last_frame.IsEmpty();
746 bool quad_has_cached_resource =
[email protected]bf691c22013-03-26 21:15:06747 renderer_->HaveCachedResourcesForRenderPassId(quad.render_pass_id);
[email protected]c1bb5af2013-03-13 19:06:27748 if (quad_has_damage) {
749 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
750 return false;
751 } else if (!quad_has_cached_resource) {
752 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
753 return false;
754 }
755 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
756 return true;
[email protected]94f206c12012-08-25 00:09:14757}
758
[email protected]c1bb5af2013-03-13 19:06:27759bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass(
760 const RenderPassDrawQuad& quad, const FrameData& frame) const {
761 const RenderPass* render_pass =
762 FindRenderPassById(quad.render_pass_id, frame);
763 if (!render_pass)
764 return false;
[email protected]94f206c12012-08-25 00:09:14765
[email protected]c1bb5af2013-03-13 19:06:27766 // If any quad or RenderPass draws into this RenderPass, then keep it.
767 const QuadList& quad_list = render_pass->quad_list;
[email protected]ed511b8d2013-03-25 03:29:29768 for (QuadList::ConstBackToFrontIterator quad_list_iterator =
769 quad_list.BackToFrontBegin();
770 quad_list_iterator != quad_list.BackToFrontEnd();
[email protected]c1bb5af2013-03-13 19:06:27771 ++quad_list_iterator) {
772 DrawQuad* current_quad = *quad_list_iterator;
[email protected]94f206c12012-08-25 00:09:14773
[email protected]c1bb5af2013-03-13 19:06:27774 if (current_quad->material != DrawQuad::RENDER_PASS)
775 return false;
[email protected]94f206c12012-08-25 00:09:14776
[email protected]c1bb5af2013-03-13 19:06:27777 const RenderPass* contributing_pass = FindRenderPassById(
778 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id, frame);
779 if (contributing_pass)
780 return false;
781 }
782 return true;
[email protected]94f206c12012-08-25 00:09:14783}
784
785// Defined for linking tests.
[email protected]c1bb5af2013-03-13 19:06:27786template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
787 LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(
788 CullRenderPassesWithCachedTextures culler, FrameData* frame);
789template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
790 LayerTreeHostImpl::CullRenderPassesWithNoQuads>(
791 CullRenderPassesWithNoQuads culler, FrameData*);
[email protected]94f206c12012-08-25 00:09:14792
793// static
[email protected]c1bb5af2013-03-13 19:06:27794template <typename RenderPassCuller>
795void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler,
796 FrameData* frame) {
797 for (size_t it = culler.RenderPassListBegin(frame->render_passes);
798 it != culler.RenderPassListEnd(frame->render_passes);
799 it = culler.RenderPassListNext(it)) {
800 const RenderPass* current_pass = frame->render_passes[it];
801 const QuadList& quad_list = current_pass->quad_list;
[email protected]ed511b8d2013-03-25 03:29:29802 QuadList::ConstBackToFrontIterator quad_list_iterator =
803 quad_list.BackToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14804
[email protected]ed511b8d2013-03-25 03:29:29805 for (; quad_list_iterator != quad_list.BackToFrontEnd();
[email protected]c1bb5af2013-03-13 19:06:27806 ++quad_list_iterator) {
807 DrawQuad* current_quad = *quad_list_iterator;
[email protected]94f206c12012-08-25 00:09:14808
[email protected]c1bb5af2013-03-13 19:06:27809 if (current_quad->material != DrawQuad::RENDER_PASS)
810 continue;
[email protected]94f206c12012-08-25 00:09:14811
[email protected]c1bb5af2013-03-13 19:06:27812 const RenderPassDrawQuad* render_pass_quad =
813 RenderPassDrawQuad::MaterialCast(current_quad);
814 if (!culler.ShouldRemoveRenderPass(*render_pass_quad, *frame))
815 continue;
[email protected]94f206c12012-08-25 00:09:14816
[email protected]c1bb5af2013-03-13 19:06:27817 // We are changing the vector in the middle of iteration. Because we
818 // delete render passes that draw into the current pass, we are
819 // guaranteed that any data from the iterator to the end will not
820 // change. So, capture the iterator position from the end of the
821 // list, and restore it after the change.
822 size_t position_from_end = frame->render_passes.size() - it;
823 RemoveRenderPassesRecursive(render_pass_quad->render_pass_id, frame);
824 it = frame->render_passes.size() - position_from_end;
825 DCHECK_GE(frame->render_passes.size(), position_from_end);
[email protected]94f206c12012-08-25 00:09:14826 }
[email protected]c1bb5af2013-03-13 19:06:27827 }
[email protected]94f206c12012-08-25 00:09:14828}
829
[email protected]c1bb5af2013-03-13 19:06:27830bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
831 TRACE_EVENT0("cc", "LayerTreeHostImpl::PrepareToDraw");
[email protected]94f206c12012-08-25 00:09:14832
[email protected]c1bb5af2013-03-13 19:06:27833 active_tree_->UpdateDrawProperties(
834 LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRAW);
[email protected]2e7ca422012-12-20 02:57:27835
[email protected]c1bb5af2013-03-13 19:06:27836 frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList();
837 frame->render_passes.clear();
838 frame->render_passes_by_id.clear();
839 frame->will_draw_layers.clear();
[email protected]94f206c12012-08-25 00:09:14840
[email protected]c1bb5af2013-03-13 19:06:27841 if (!CalculateRenderPasses(frame))
842 return false;
[email protected]94f206c12012-08-25 00:09:14843
[email protected]c1bb5af2013-03-13 19:06:27844 // If we return true, then we expect DrawLayers() to be called before this
845 // function is called again.
846 return true;
[email protected]94f206c12012-08-25 00:09:14847}
848
[email protected]c1bb5af2013-03-13 19:06:27849void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
850 const ManagedMemoryPolicy& policy) {
851 bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread(
[email protected]46b8acc2013-03-19 22:38:35852 visible_ ? policy.bytes_limit_when_visible
853 : policy.bytes_limit_when_not_visible,
854 ManagedMemoryPolicy::PriorityCutoffToValue(
855 visible_ ? policy.priority_cutoff_when_visible
856 : policy.priority_cutoff_when_not_visible));
[email protected]c1bb5af2013-03-13 19:06:27857 if (evicted_resources) {
858 active_tree_->SetContentsTexturesPurged();
859 if (pending_tree_)
860 pending_tree_->SetContentsTexturesPurged();
861 client_->SetNeedsCommitOnImplThread();
862 client_->OnCanDrawStateChanged(CanDraw());
863 client_->RenewTreePriority();
864 }
865 client_->SendManagedMemoryStats();
[email protected]8947cbe2012-11-28 05:27:43866
[email protected]c1bb5af2013-03-13 19:06:27867 if (tile_manager_) {
868 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
869 new_state.memory_limit_in_bytes = visible_ ?
[email protected]46b8acc2013-03-19 22:38:35870 policy.bytes_limit_when_visible :
871 policy.bytes_limit_when_not_visible;
[email protected]41124c52013-03-28 23:26:57872 // TODO(reveman): We should avoid keeping around unused resources if
873 // possible. crbug.com/224475
874 new_state.unused_memory_limit_in_bytes =
875 (new_state.memory_limit_in_bytes *
876 settings_.max_unused_resource_memory_percentage) / 100;
[email protected]c1bb5af2013-03-13 19:06:27877 new_state.memory_limit_policy =
[email protected]46b8acc2013-03-19 22:38:35878 ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy(
[email protected]c1bb5af2013-03-13 19:06:27879 visible_ ?
[email protected]46b8acc2013-03-19 22:38:35880 policy.priority_cutoff_when_visible :
881 policy.priority_cutoff_when_not_visible);
[email protected]c1bb5af2013-03-13 19:06:27882 tile_manager_->SetGlobalState(new_state);
883 }
[email protected]94f206c12012-08-25 00:09:14884}
885
[email protected]c1bb5af2013-03-13 19:06:27886bool LayerTreeHostImpl::HasImplThread() const {
887 return proxy_->HasImplThread();
[email protected]61de5812012-11-08 07:03:44888}
889
[email protected]c1bb5af2013-03-13 19:06:27890void LayerTreeHostImpl::ScheduleManageTiles() {
891 if (client_)
892 client_->SetNeedsManageTilesOnImplThread();
[email protected]8947cbe2012-11-28 05:27:43893}
894
[email protected]86126792013-03-16 20:07:54895void LayerTreeHostImpl::DidInitializeVisibleTile() {
896 // TODO(reveman): Determine tiles that changed and only damage
897 // what's necessary.
898 SetFullRootLayerDamage();
[email protected]c1bb5af2013-03-13 19:06:27899 if (client_)
[email protected]86126792013-03-16 20:07:54900 client_->DidInitializeVisibleTileOnImplThread();
[email protected]74d9063c2013-01-18 03:14:47901}
902
[email protected]c1bb5af2013-03-13 19:06:27903bool LayerTreeHostImpl::ShouldClearRootRenderPass() const {
[email protected]8e0176d2013-03-21 03:14:52904 return settings_.should_clear_root_render_pass;
[email protected]f35e2322012-12-15 21:45:52905}
906
[email protected]c1bb5af2013-03-13 19:06:27907void LayerTreeHostImpl::SetManagedMemoryPolicy(
908 const ManagedMemoryPolicy& policy) {
909 if (managed_memory_policy_ == policy)
910 return;
[email protected]61de5812012-11-08 07:03:44911
[email protected]d7626ffd2013-03-29 00:17:42912 // If there is already enough memory to draw everything imaginable and the
913 // new memory limit does not change this, then do not re-commit. Don't bother
914 // skipping commits if this is not visible (commits don't happen when not
915 // visible, there will almost always be a commit when this becomes visible).
916 bool needs_commit = true;
917 if (visible() &&
918 policy.bytes_limit_when_visible >=
919 max_memory_needed_bytes_ &&
920 managed_memory_policy_.bytes_limit_when_visible >=
921 max_memory_needed_bytes_ &&
922 policy.priority_cutoff_when_visible ==
923 managed_memory_policy_.priority_cutoff_when_visible) {
924 needs_commit = false;
925 }
926
[email protected]c1bb5af2013-03-13 19:06:27927 managed_memory_policy_ = policy;
928 if (!proxy_->HasImplThread()) {
[email protected]d7626ffd2013-03-29 00:17:42929 // In single-thread mode, this can be called on the main thread by
930 // GLRenderer::OnMemoryAllocationChanged.
[email protected]c1bb5af2013-03-13 19:06:27931 DebugScopedSetImplThread impl_thread(proxy_);
932 EnforceManagedMemoryPolicy(managed_memory_policy_);
933 } else {
934 DCHECK(proxy_->IsImplThread());
935 EnforceManagedMemoryPolicy(managed_memory_policy_);
936 }
[email protected]d7626ffd2013-03-29 00:17:42937
938 if (needs_commit)
939 client_->SetNeedsCommitOnImplThread();
[email protected]94f206c12012-08-25 00:09:14940}
941
[email protected]c1bb5af2013-03-13 19:06:27942void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase,
943 base::TimeDelta interval) {
944 client_->OnVSyncParametersChanged(timebase, interval);
[email protected]94f206c12012-08-25 00:09:14945}
946
[email protected]7ed47512013-03-26 22:28:45947void LayerTreeHostImpl::DidVSync(base::TimeTicks frame_time) {
948 client_->DidVSync(frame_time);
949}
950
[email protected]c1bb5af2013-03-13 19:06:27951void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(
952 const CompositorFrameAck& ack) {
953 if (!renderer_)
954 return;
[email protected]b6f3d7e2012-12-08 00:11:21955
[email protected]c1bb5af2013-03-13 19:06:27956 // TODO(piman): We may need to do some validation on this ack before
957 // processing it.
958 renderer_->ReceiveCompositorFrameAck(ack);
[email protected]a46f32932012-12-07 21:43:16959}
960
[email protected]c1bb5af2013-03-13 19:06:27961void LayerTreeHostImpl::OnCanDrawStateChangedForTree() {
962 client_->OnCanDrawStateChanged(CanDraw());
[email protected]3b31c6ac2012-12-06 21:27:29963}
964
[email protected]c1bb5af2013-03-13 19:06:27965CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
966 CompositorFrameMetadata metadata;
967 metadata.device_scale_factor = device_scale_factor_;
968 metadata.page_scale_factor = active_tree_->total_page_scale_factor();
969 metadata.viewport_size = active_tree_->ScrollableViewportSize();
970 metadata.root_layer_size = active_tree_->ScrollableSize();
971 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
972 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor();
973 if (top_controls_manager_) {
974 metadata.location_bar_offset =
975 gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset());
976 metadata.location_bar_content_translation =
977 gfx::Vector2dF(0.f, top_controls_manager_->content_top_offset());
[email protected]5a54b2822013-03-26 10:00:01978 metadata.overdraw_bottom_height = overdraw_bottom_height_;
[email protected]c1bb5af2013-03-13 19:06:27979 }
[email protected]bf189f62012-12-18 03:42:11980
[email protected]c1bb5af2013-03-13 19:06:27981 if (!RootScrollLayer())
[email protected]bf189f62012-12-18 03:42:11982 return metadata;
[email protected]c1bb5af2013-03-13 19:06:27983
[email protected]ffb2720f2013-03-15 19:18:37984 metadata.root_scroll_offset = RootScrollLayer()->TotalScrollOffset();
[email protected]c1bb5af2013-03-13 19:06:27985
986 return metadata;
[email protected]bf189f62012-12-18 03:42:11987}
988
[email protected]73673592013-04-03 22:14:32989bool LayerTreeHostImpl::AllowPartialSwap() const {
990 // We don't track damage on the HUD layer (it interacts with damage tracking
991 // visualizations), so disable partial swaps to make the HUD layer display
992 // properly.
993 return !debug_state_.ShowHudRects();
994}
995
[email protected]f0c2a242013-03-15 19:34:52996void LayerTreeHostImpl::DrawLayers(FrameData* frame,
997 base::TimeTicks frame_begin_time) {
[email protected]c1bb5af2013-03-13 19:06:27998 TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
999 DCHECK(CanDraw());
1000 DCHECK(!frame->render_passes.empty());
[email protected]94f206c12012-08-25 00:09:141001
[email protected]9e3594522013-03-18 00:57:361002 fps_counter_->SaveTimeStamp(frame_begin_time);
[email protected]94f206c12012-08-25 00:09:141003
[email protected]372bad5f2013-03-21 16:38:431004 rendering_stats_instrumentation_->SetScreenFrameCount(
1005 fps_counter_->current_frame_number());
1006 rendering_stats_instrumentation_->SetDroppedFrameCount(
1007 fps_counter_->dropped_frame_count());
1008
[email protected]c1bb5af2013-03-13 19:06:271009 if (tile_manager_) {
1010 memory_history_->SaveEntry(
1011 tile_manager_->memory_stats_from_last_assign());
1012 }
[email protected]1191d9d2013-02-02 06:00:331013
[email protected]846f455b2013-03-18 19:07:411014 if (debug_state_.ShowHudRects()) {
[email protected]d35992782013-03-14 14:54:021015 debug_rect_history_->SaveDebugRectsForCurrentFrame(
[email protected]c1bb5af2013-03-13 19:06:271016 active_tree_->root_layer(),
1017 *frame->render_surface_layer_list,
1018 frame->occluding_screen_space_rects,
1019 frame->non_occluding_screen_space_rects,
1020 debug_state_);
1021 }
[email protected]94f206c12012-08-25 00:09:141022
[email protected]a848c102013-03-26 08:59:091023 if (!settings_.impl_side_painting && debug_state_.continuous_painting) {
1024 const RenderingStats& stats =
1025 rendering_stats_instrumentation_->GetRenderingStats();
1026 paint_time_counter_->SavePaintTime(stats.total_paint_time);
1027 }
1028
[email protected]846f455b2013-03-18 19:07:411029 if (debug_state_.trace_all_rendered_frames) {
[email protected]c76faea2013-03-26 07:42:421030 TRACE_EVENT_INSTANT1("cc.debug", "Frame", TRACE_EVENT_SCOPE_THREAD,
[email protected]c1bb5af2013-03-13 19:06:271031 "frame", ValueToString(FrameStateAsValue()));
1032 }
[email protected]131a0c22013-02-12 18:31:081033
[email protected]c1bb5af2013-03-13 19:06:271034 // Because the contents of the HUD depend on everything else in the frame, the
1035 // contents of its texture are updated as the last thing before the frame is
1036 // drawn.
1037 if (active_tree_->hud_layer())
[email protected]264dc0332013-03-17 21:00:541038 active_tree_->hud_layer()->UpdateHudTexture(resource_provider_.get());
[email protected]94f206c12012-08-25 00:09:141039
[email protected]d002dd02013-03-27 07:40:401040 renderer_->DrawFrame(&frame->render_passes);
[email protected]c1bb5af2013-03-13 19:06:271041 // The render passes should be consumed by the renderer.
1042 DCHECK(frame->render_passes.empty());
1043 frame->render_passes_by_id.clear();
[email protected]94f206c12012-08-25 00:09:141044
[email protected]c1bb5af2013-03-13 19:06:271045 // The next frame should start by assuming nothing has changed, and changes
1046 // are noted as they occur.
[email protected]264dc0332013-03-17 21:00:541047 for (size_t i = 0; i < frame->render_surface_layer_list->size(); i++) {
[email protected]c1bb5af2013-03-13 19:06:271048 (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()->
1049 DidDrawDamagedArea();
1050 }
1051 active_tree_->root_layer()->ResetAllChangeTrackingForSubtree();
[email protected]94f206c12012-08-25 00:09:141052}
1053
[email protected]c1bb5af2013-03-13 19:06:271054void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) {
1055 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i)
1056 frame.will_draw_layers[i]->DidDraw(resource_provider_.get());
[email protected]b914e102012-10-02 08:11:521057
[email protected]c1bb5af2013-03-13 19:06:271058 // Once all layers have been drawn, pending texture uploads should no
1059 // longer block future uploads.
1060 resource_provider_->MarkPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:141061}
1062
[email protected]c1bb5af2013-03-13 19:06:271063void LayerTreeHostImpl::FinishAllRendering() {
1064 if (renderer_)
1065 renderer_->Finish();
[email protected]94f206c12012-08-25 00:09:141066}
1067
[email protected]c1bb5af2013-03-13 19:06:271068bool LayerTreeHostImpl::IsContextLost() {
1069 DCHECK(proxy_->IsImplThread());
1070 return renderer_ && renderer_->IsContextLost();
[email protected]94f206c12012-08-25 00:09:141071}
1072
[email protected]c1bb5af2013-03-13 19:06:271073const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const {
1074 return renderer_->Capabilities();
[email protected]94f206c12012-08-25 00:09:141075}
1076
[email protected]c1bb5af2013-03-13 19:06:271077bool LayerTreeHostImpl::SwapBuffers() {
[email protected]c1bb5af2013-03-13 19:06:271078 return renderer_->SwapBuffers();
[email protected]94f206c12012-08-25 00:09:141079}
1080
[email protected]7ed47512013-03-26 22:28:451081void LayerTreeHostImpl::EnableVSyncNotification(bool enable) {
1082 if (output_surface_)
1083 output_surface_->EnableVSyncNotification(enable);
1084}
1085
[email protected]c1bb5af2013-03-13 19:06:271086gfx::Size LayerTreeHostImpl::DeviceViewportSize() const {
1087 return device_viewport_size();
[email protected]493067512012-09-19 23:34:101088}
1089
[email protected]ffb2720f2013-03-15 19:18:371090gfx::SizeF LayerTreeHostImpl::VisibleViewportSize() const {
1091 gfx::SizeF dip_size =
1092 gfx::ScaleSize(DeviceViewportSize(), 1.f / device_scale_factor());
1093
1094 // The clip layer should be used if non-overlay scrollbars may exist since
1095 // it adjusts for them.
1096 LayerImpl* clip_layer = active_tree_->RootClipLayer();
[email protected]8e0176d2013-03-21 03:14:521097 if (!Settings().solid_color_scrollbars && clip_layer &&
[email protected]ffb2720f2013-03-15 19:18:371098 clip_layer->masks_to_bounds())
1099 dip_size = clip_layer->bounds();
1100
[email protected]ed511b8d2013-03-25 03:29:291101 float top_offset =
[email protected]ffb2720f2013-03-15 19:18:371102 top_controls_manager_ ? top_controls_manager_->content_top_offset() : 0.f;
[email protected]d9083762013-03-24 01:36:401103 return gfx::SizeF(dip_size.width(),
[email protected]ed511b8d2013-03-25 03:29:291104 dip_size.height() - top_offset - overdraw_bottom_height_);
[email protected]ffb2720f2013-03-15 19:18:371105}
1106
[email protected]c1bb5af2013-03-13 19:06:271107const LayerTreeSettings& LayerTreeHostImpl::Settings() const {
1108 return settings();
[email protected]493067512012-09-19 23:34:101109}
1110
[email protected]c1bb5af2013-03-13 19:06:271111void LayerTreeHostImpl::DidLoseOutputSurface() {
1112 client_->DidLoseOutputSurfaceOnImplThread();
[email protected]94f206c12012-08-25 00:09:141113}
1114
[email protected]c1bb5af2013-03-13 19:06:271115void LayerTreeHostImpl::OnSwapBuffersComplete() {
1116 client_->OnSwapBuffersCompleteOnImplThread();
[email protected]94f206c12012-08-25 00:09:141117}
1118
[email protected]c1bb5af2013-03-13 19:06:271119void LayerTreeHostImpl::Readback(void* pixels,
1120 gfx::Rect rect_in_device_viewport) {
1121 DCHECK(renderer_);
1122 renderer_->GetFramebufferPixels(pixels, rect_in_device_viewport);
[email protected]94f206c12012-08-25 00:09:141123}
1124
[email protected]69b50ec2013-01-19 04:58:011125bool LayerTreeHostImpl::haveRootScrollLayer() const {
[email protected]3209161d2013-03-29 19:17:341126 return !!RootScrollLayer();
[email protected]69b50ec2013-01-19 04:58:011127}
1128
[email protected]c1bb5af2013-03-13 19:06:271129LayerImpl* LayerTreeHostImpl::RootLayer() const {
1130 return active_tree_->root_layer();
[email protected]8bef40572012-12-11 21:38:081131}
1132
[email protected]c1bb5af2013-03-13 19:06:271133LayerImpl* LayerTreeHostImpl::RootScrollLayer() const {
1134 return active_tree_->RootScrollLayer();
[email protected]8bef40572012-12-11 21:38:081135}
1136
[email protected]c1bb5af2013-03-13 19:06:271137LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
1138 return active_tree_->CurrentlyScrollingLayer();
[email protected]8bef40572012-12-11 21:38:081139}
1140
[email protected]94f206c12012-08-25 00:09:141141// Content layers can be either directly scrollable or contained in an outer
1142// scrolling layer which applies the scroll transform. Given a content layer,
1143// this function returns the associated scroll layer if any.
[email protected]c1bb5af2013-03-13 19:06:271144static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) {
1145 if (!layer_impl)
[email protected]94f206c12012-08-25 00:09:141146 return 0;
[email protected]c1bb5af2013-03-13 19:06:271147
1148 if (layer_impl->scrollable())
1149 return layer_impl;
1150
1151 if (layer_impl->DrawsContent() &&
1152 layer_impl->parent() &&
1153 layer_impl->parent()->scrollable())
1154 return layer_impl->parent();
1155
1156 return 0;
[email protected]94f206c12012-08-25 00:09:141157}
1158
[email protected]c1bb5af2013-03-13 19:06:271159void LayerTreeHostImpl::CreatePendingTree() {
1160 CHECK(!pending_tree_);
1161 if (recycle_tree_)
1162 recycle_tree_.swap(pending_tree_);
1163 else
1164 pending_tree_ = LayerTreeImpl::create(this);
1165 client_->OnCanDrawStateChanged(CanDraw());
1166 client_->OnHasPendingTreeStateChanged(pending_tree_);
1167 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get());
1168 TRACE_EVENT_ASYNC_STEP0("cc",
1169 "PendingTree", pending_tree_.get(), "waiting");
[email protected]2e7ca422012-12-20 02:57:271170}
1171
[email protected]c1bb5af2013-03-13 19:06:271172void LayerTreeHostImpl::CheckForCompletedTileUploads() {
1173 DCHECK(!client_->IsInsideDraw()) <<
1174 "Checking for completed uploads within a draw may trigger "
1175 "spurious redraws.";
1176 if (tile_manager_)
1177 tile_manager_->CheckForCompletedTileUploads();
[email protected]eabe5002013-01-12 22:07:481178}
1179
[email protected]c1bb5af2013-03-13 19:06:271180bool LayerTreeHostImpl::ActivatePendingTreeIfNeeded() {
1181 if (!pending_tree_)
1182 return false;
[email protected]2e7ca422012-12-20 02:57:271183
[email protected]c1bb5af2013-03-13 19:06:271184 CHECK(tile_manager_);
[email protected]2ae038b2013-01-28 12:52:091185
[email protected]c1bb5af2013-03-13 19:06:271186 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE);
[email protected]615c78a2013-01-24 23:44:161187
[email protected]c1bb5af2013-03-13 19:06:271188 TRACE_EVENT_ASYNC_STEP1("cc",
1189 "PendingTree", pending_tree_.get(), "activate",
1190 "state", ValueToString(ActivationStateAsValue()));
[email protected]4f0a5002013-01-28 13:02:271191
[email protected]8ca1e6c2013-04-02 03:49:261192 // Activate once all visible resources in pending tree are ready.
1193 if (!pending_tree_->AreVisibleResourcesReady())
1194 return false;
[email protected]2e7ca422012-12-20 02:57:271195
[email protected]c1bb5af2013-03-13 19:06:271196 ActivatePendingTree();
1197 return true;
[email protected]2e7ca422012-12-20 02:57:271198}
1199
[email protected]c1bb5af2013-03-13 19:06:271200void LayerTreeHostImpl::ActivatePendingTree() {
1201 CHECK(pending_tree_);
1202 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get());
[email protected]1e0f8d62013-01-09 07:41:351203
[email protected]c1bb5af2013-03-13 19:06:271204 active_tree_->PushPersistedState(pending_tree_.get());
1205 if (pending_tree_->needs_full_tree_sync()) {
1206 active_tree_->SetRootLayer(
[email protected]b5651c22013-03-14 15:06:331207 TreeSynchronizer::SynchronizeTrees(pending_tree_->root_layer(),
[email protected]c1bb5af2013-03-13 19:06:271208 active_tree_->DetachLayerTree(),
1209 active_tree_.get()));
1210 }
[email protected]b5651c22013-03-14 15:06:331211 TreeSynchronizer::PushProperties(pending_tree_->root_layer(),
[email protected]c1bb5af2013-03-13 19:06:271212 active_tree_->root_layer());
1213 DCHECK(!recycle_tree_);
[email protected]48871fc2013-01-23 07:36:511214
[email protected]c1bb5af2013-03-13 19:06:271215 pending_tree_->PushPropertiesTo(active_tree_.get());
[email protected]48871fc2013-01-23 07:36:511216
[email protected]c1bb5af2013-03-13 19:06:271217 // Now that we've synced everything from the pending tree to the active
1218 // tree, rename the pending tree the recycle tree so we can reuse it on the
1219 // next sync.
1220 pending_tree_.swap(recycle_tree_);
1221 recycle_tree_->ClearRenderSurfaces();
[email protected]48871fc2013-01-23 07:36:511222
[email protected]c1bb5af2013-03-13 19:06:271223 active_tree_->DidBecomeActive();
[email protected]37386f052013-01-13 00:42:221224
[email protected]c1bb5af2013-03-13 19:06:271225 // Reduce wasted memory now that unlinked resources are guaranteed not
1226 // to be used.
1227 client_->ReduceWastedContentsTextureMemoryOnImplThread();
[email protected]a0b84172013-02-04 08:13:411228
[email protected]c1bb5af2013-03-13 19:06:271229 client_->OnCanDrawStateChanged(CanDraw());
1230 client_->OnHasPendingTreeStateChanged(pending_tree_);
1231 client_->SetNeedsRedrawOnImplThread();
1232 client_->RenewTreePriority();
[email protected]652cf132013-02-15 21:53:241233
[email protected]a848c102013-03-26 08:59:091234 if (debug_state_.continuous_painting) {
1235 const RenderingStats& stats =
[email protected]372bad5f2013-03-21 16:38:431236 rendering_stats_instrumentation_->GetRenderingStats();
[email protected]a848c102013-03-26 08:59:091237 paint_time_counter_->SavePaintTime(
1238 stats.total_paint_time +
1239 stats.total_rasterize_time_for_now_bins_on_pending_tree);
[email protected]c1bb5af2013-03-13 19:06:271240 }
[email protected]2e7ca422012-12-20 02:57:271241}
1242
[email protected]c1bb5af2013-03-13 19:06:271243void LayerTreeHostImpl::SetVisible(bool visible) {
1244 DCHECK(proxy_->IsImplThread());
[email protected]94f206c12012-08-25 00:09:141245
[email protected]c1bb5af2013-03-13 19:06:271246 if (visible_ == visible)
1247 return;
1248 visible_ = visible;
1249 DidVisibilityChange(this, visible_);
1250 EnforceManagedMemoryPolicy(managed_memory_policy_);
[email protected]94f206c12012-08-25 00:09:141251
[email protected]c1bb5af2013-03-13 19:06:271252 if (!renderer_)
1253 return;
[email protected]94f206c12012-08-25 00:09:141254
[email protected]c1bb5af2013-03-13 19:06:271255 renderer_->SetVisible(visible);
[email protected]94f206c12012-08-25 00:09:141256}
1257
[email protected]c1bb5af2013-03-13 19:06:271258bool LayerTreeHostImpl::InitializeRenderer(
1259 scoped_ptr<OutputSurface> output_surface) {
1260 // Since we will create a new resource provider, we cannot continue to use
1261 // the old resources (i.e. render_surfaces and texture IDs). Clear them
1262 // before we destroy the old resource provider.
1263 if (active_tree_->root_layer())
1264 ClearRenderSurfaces();
1265 if (active_tree_->root_layer())
1266 SendDidLoseOutputSurfaceRecursive(active_tree_->root_layer());
1267 if (pending_tree_ && pending_tree_->root_layer())
1268 SendDidLoseOutputSurfaceRecursive(pending_tree_->root_layer());
1269 if (recycle_tree_ && recycle_tree_->root_layer())
1270 SendDidLoseOutputSurfaceRecursive(recycle_tree_->root_layer());
[email protected]45c4b1e2013-01-16 02:19:401271
[email protected]c1bb5af2013-03-13 19:06:271272 // Note: order is important here.
1273 renderer_.reset();
1274 tile_manager_.reset();
1275 resource_provider_.reset();
1276 output_surface_.reset();
[email protected]94f206c12012-08-25 00:09:141277
[email protected]c1bb5af2013-03-13 19:06:271278 if (!output_surface->BindToClient(this))
1279 return false;
[email protected]be3181652012-09-25 13:02:131280
[email protected]075d8aa2013-04-01 23:03:111281 scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
1282 output_surface.get(), settings_.highp_threshold_min);
[email protected]c1bb5af2013-03-13 19:06:271283 if (!resource_provider)
1284 return false;
[email protected]be3181652012-09-25 13:02:131285
[email protected]8e0176d2013-03-21 03:14:521286 if (settings_.impl_side_painting) {
[email protected]c1bb5af2013-03-13 19:06:271287 tile_manager_.reset(new TileManager(this,
1288 resource_provider.get(),
[email protected]8e0176d2013-03-21 03:14:521289 settings_.num_raster_threads,
[email protected]d616de012013-03-28 07:19:101290 settings_.max_prepaint_tile_distance,
[email protected]8e0176d2013-03-21 03:14:521291 settings_.use_cheapness_estimator,
1292 settings_.use_color_estimator,
[email protected]372bad5f2013-03-21 16:38:431293 settings_.prediction_benchmarking,
1294 rendering_stats_instrumentation_));
[email protected]c1bb5af2013-03-13 19:06:271295 }
[email protected]8947cbe2012-11-28 05:27:431296
[email protected]c1bb5af2013-03-13 19:06:271297 if (output_surface->capabilities().has_parent_compositor) {
1298 renderer_ = DelegatingRenderer::Create(this, output_surface.get(),
1299 resource_provider.get());
1300 } else if (output_surface->context3d()) {
1301 renderer_ = GLRenderer::Create(this,
1302 output_surface.get(),
[email protected]075d8aa2013-04-01 23:03:111303 resource_provider.get(),
1304 settings_.highp_threshold_min);
[email protected]c1bb5af2013-03-13 19:06:271305 } else if (output_surface->software_device()) {
1306 renderer_ = SoftwareRenderer::Create(this,
1307 output_surface.get(),
1308 resource_provider.get());
1309 }
1310 if (!renderer_)
1311 return false;
[email protected]be3181652012-09-25 13:02:131312
[email protected]c1bb5af2013-03-13 19:06:271313 resource_provider_ = resource_provider.Pass();
1314 output_surface_ = output_surface.Pass();
[email protected]94f206c12012-08-25 00:09:141315
[email protected]c1bb5af2013-03-13 19:06:271316 if (!visible_)
1317 renderer_->SetVisible(visible_);
[email protected]94f206c12012-08-25 00:09:141318
[email protected]c1bb5af2013-03-13 19:06:271319 client_->OnCanDrawStateChanged(CanDraw());
[email protected]8db2213c2012-09-05 22:08:211320
[email protected]c1bb5af2013-03-13 19:06:271321 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs
1322 // to be initialized to get max texture size.
1323 active_tree_->set_needs_update_draw_properties();
1324 if (pending_tree_)
1325 pending_tree_->set_needs_update_draw_properties();
[email protected]615c78a2013-01-24 23:44:161326
[email protected]c1bb5af2013-03-13 19:06:271327 return true;
[email protected]94f206c12012-08-25 00:09:141328}
1329
[email protected]c1bb5af2013-03-13 19:06:271330void LayerTreeHostImpl::SetViewportSize(gfx::Size layout_viewport_size,
1331 gfx::Size device_viewport_size) {
1332 if (layout_viewport_size == layout_viewport_size_ &&
1333 device_viewport_size == device_viewport_size_)
1334 return;
[email protected]94f206c12012-08-25 00:09:141335
[email protected]c1bb5af2013-03-13 19:06:271336 if (pending_tree_ && device_viewport_size_ != device_viewport_size)
1337 active_tree_->SetViewportSizeInvalid();
[email protected]318822852013-02-14 00:54:271338
[email protected]c1bb5af2013-03-13 19:06:271339 layout_viewport_size_ = layout_viewport_size;
1340 device_viewport_size_ = device_viewport_size;
[email protected]94f206c12012-08-25 00:09:141341
[email protected]c1bb5af2013-03-13 19:06:271342 UpdateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141343
[email protected]c1bb5af2013-03-13 19:06:271344 if (renderer_)
1345 renderer_->ViewportChanged();
[email protected]8db2213c2012-09-05 22:08:211346
[email protected]c1bb5af2013-03-13 19:06:271347 client_->OnCanDrawStateChanged(CanDraw());
[email protected]94f206c12012-08-25 00:09:141348}
1349
[email protected]c1bb5af2013-03-13 19:06:271350static void AdjustScrollsForPageScaleChange(LayerImpl* layer_impl,
1351 float page_scale_change) {
1352 if (!layer_impl)
1353 return;
[email protected]94f206c12012-08-25 00:09:141354
[email protected]c1bb5af2013-03-13 19:06:271355 if (layer_impl->scrollable()) {
1356 // We need to convert impl-side scroll deltas to page_scale space.
1357 gfx::Vector2dF scroll_delta = layer_impl->scroll_delta();
1358 scroll_delta.Scale(page_scale_change);
1359 layer_impl->SetScrollDelta(scroll_delta);
1360 }
[email protected]94f206c12012-08-25 00:09:141361
[email protected]c1bb5af2013-03-13 19:06:271362 for (size_t i = 0; i < layer_impl->children().size(); ++i)
1363 AdjustScrollsForPageScaleChange(layer_impl->children()[i],
1364 page_scale_change);
[email protected]94f206c12012-08-25 00:09:141365}
1366
[email protected]d9083762013-03-24 01:36:401367void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) {
1368 if (overdraw_bottom_height == overdraw_bottom_height_)
1369 return;
1370 overdraw_bottom_height_ = overdraw_bottom_height;
1371
1372 UpdateMaxScrollOffset();
1373}
1374
[email protected]c1bb5af2013-03-13 19:06:271375void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
1376 if (device_scale_factor == device_scale_factor_)
1377 return;
1378 device_scale_factor_ = device_scale_factor;
[email protected]c0dd24c2012-08-30 23:25:271379
[email protected]c1bb5af2013-03-13 19:06:271380 UpdateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141381}
1382
[email protected]c1bb5af2013-03-13 19:06:271383void LayerTreeHostImpl::UpdateMaxScrollOffset() {
1384 active_tree_->UpdateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141385}
1386
[email protected]c1bb5af2013-03-13 19:06:271387void LayerTreeHostImpl::setActiveTreeNeedsUpdateDrawProperties() {
1388 active_tree_->set_needs_update_draw_properties();
[email protected]3ba4cae2013-01-16 03:58:381389}
1390
[email protected]c1bb5af2013-03-13 19:06:271391void LayerTreeHostImpl::setNeedsRedraw() {
1392 client_->SetNeedsRedrawOnImplThread();
[email protected]94f206c12012-08-25 00:09:141393}
1394
[email protected]c1bb5af2013-03-13 19:06:271395bool LayerTreeHostImpl::EnsureRenderSurfaceLayerList() {
1396 active_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE);
[email protected]3209161d2013-03-29 19:17:341397 return !active_tree_->RenderSurfaceLayerList().empty();
[email protected]94f206c12012-08-25 00:09:141398}
1399
[email protected]c1bb5af2013-03-13 19:06:271400InputHandlerClient::ScrollStatus LayerTreeHostImpl::ScrollBegin(
1401 gfx::Point viewport_point, InputHandlerClient::ScrollInputType type) {
[email protected]ed511b8d2013-03-25 03:29:291402 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin");
[email protected]94f206c12012-08-25 00:09:141403
[email protected]c1bb5af2013-03-13 19:06:271404 if (top_controls_manager_)
1405 top_controls_manager_->ScrollBegin();
[email protected]3ba4cae2013-01-16 03:58:381406
[email protected]c1bb5af2013-03-13 19:06:271407 DCHECK(!CurrentlyScrollingLayer());
1408 ClearCurrentlyScrollingLayer();
[email protected]94f206c12012-08-25 00:09:141409
[email protected]c1bb5af2013-03-13 19:06:271410 if (!EnsureRenderSurfaceLayerList())
[email protected]94f206c12012-08-25 00:09:141411 return ScrollIgnored;
[email protected]94f206c12012-08-25 00:09:141412
[email protected]c1bb5af2013-03-13 19:06:271413 gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
1414 device_scale_factor_);
[email protected]94f206c12012-08-25 00:09:141415
[email protected]c1bb5af2013-03-13 19:06:271416 // First find out which layer was hit from the saved list of visible layers
1417 // in the most recent frame.
[email protected]6ba914122013-03-22 16:26:391418 LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
[email protected]c1bb5af2013-03-13 19:06:271419 device_viewport_point, active_tree_->RenderSurfaceLayerList());
[email protected]31bfe272012-10-19 18:49:521420
[email protected]c1bb5af2013-03-13 19:06:271421 // Walk up the hierarchy and look for a scrollable layer.
1422 LayerImpl* potentially_scrolling_layer_impl = 0;
1423 for (; layer_impl; layer_impl = layer_impl->parent()) {
1424 // The content layer can also block attempts to scroll outside the main
1425 // thread.
1426 ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
1427 if (status == ScrollOnMainThread) {
[email protected]372bad5f2013-03-21 16:38:431428 rendering_stats_instrumentation_->IncrementMainThreadScrolls();
[email protected]c1bb5af2013-03-13 19:06:271429 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
[email protected]b7c4783f2013-03-15 23:11:421430 active_tree()->DidBeginScroll();
[email protected]c1bb5af2013-03-13 19:06:271431 return ScrollOnMainThread;
[email protected]94f206c12012-08-25 00:09:141432 }
1433
[email protected]c1bb5af2013-03-13 19:06:271434 LayerImpl* scroll_layer_impl = FindScrollLayerForContentLayer(layer_impl);
1435 if (!scroll_layer_impl)
1436 continue;
[email protected]94f206c12012-08-25 00:09:141437
[email protected]c1bb5af2013-03-13 19:06:271438 status = scroll_layer_impl->TryScroll(device_viewport_point, type);
[email protected]94f206c12012-08-25 00:09:141439
[email protected]c1bb5af2013-03-13 19:06:271440 // If any layer wants to divert the scroll event to the main thread, abort.
1441 if (status == ScrollOnMainThread) {
[email protected]372bad5f2013-03-21 16:38:431442 rendering_stats_instrumentation_->IncrementMainThreadScrolls();
[email protected]c1bb5af2013-03-13 19:06:271443 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
[email protected]b7c4783f2013-03-15 23:11:421444 active_tree()->DidBeginScroll();
[email protected]c1bb5af2013-03-13 19:06:271445 return ScrollOnMainThread;
[email protected]94f206c12012-08-25 00:09:141446 }
1447
[email protected]c1bb5af2013-03-13 19:06:271448 if (status == ScrollStarted && !potentially_scrolling_layer_impl)
1449 potentially_scrolling_layer_impl = scroll_layer_impl;
1450 }
1451
1452 // When hiding top controls is enabled and the controls are hidden or
1453 // overlaying the content, force scrolls to be enabled on the root layer to
1454 // allow bringing the top controls back into view.
1455 if (!potentially_scrolling_layer_impl && top_controls_manager_ &&
1456 top_controls_manager_->content_top_offset() !=
[email protected]8e0176d2013-03-21 03:14:521457 settings_.top_controls_height) {
[email protected]c1bb5af2013-03-13 19:06:271458 potentially_scrolling_layer_impl = RootScrollLayer();
1459 }
1460
1461 if (potentially_scrolling_layer_impl) {
[email protected]0fc818e2013-03-18 06:45:201462 active_tree_->SetCurrentlyScrollingLayer(
[email protected]c1bb5af2013-03-13 19:06:271463 potentially_scrolling_layer_impl);
1464 should_bubble_scrolls_ = (type != NonBubblingGesture);
1465 wheel_scrolling_ = (type == Wheel);
[email protected]372bad5f2013-03-21 16:38:431466 rendering_stats_instrumentation_->IncrementImplThreadScrolls();
[email protected]c1bb5af2013-03-13 19:06:271467 client_->RenewTreePriority();
1468 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
[email protected]b7c4783f2013-03-15 23:11:421469 active_tree()->DidBeginScroll();
[email protected]c1bb5af2013-03-13 19:06:271470 return ScrollStarted;
1471 }
1472 return ScrollIgnored;
[email protected]94f206c12012-08-25 00:09:141473}
1474
[email protected]c1bb5af2013-03-13 19:06:271475gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta(
1476 LayerImpl* layer_impl,
1477 float scale_from_viewport_to_screen_space,
1478 gfx::PointF viewport_point,
1479 gfx::Vector2dF viewport_delta) {
1480 // Layers with non-invertible screen space transforms should not have passed
1481 // the scroll hit test in the first place.
1482 DCHECK(layer_impl->screen_space_transform().IsInvertible());
1483 gfx::Transform inverse_screen_space_transform(
1484 gfx::Transform::kSkipInitialization);
1485 bool did_invert = layer_impl->screen_space_transform().GetInverse(
1486 &inverse_screen_space_transform);
[email protected]ca2902e92013-03-28 01:45:351487 // TODO(shawnsingh): With the advent of impl-side crolling for non-root
1488 // layers, we may need to explicitly handle uninvertible transforms here.
[email protected]c1bb5af2013-03-13 19:06:271489 DCHECK(did_invert);
[email protected]94f206c12012-08-25 00:09:141490
[email protected]c1bb5af2013-03-13 19:06:271491 gfx::PointF screen_space_point =
1492 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space);
[email protected]94f206c12012-08-25 00:09:141493
[email protected]c1bb5af2013-03-13 19:06:271494 gfx::Vector2dF screen_space_delta = viewport_delta;
1495 screen_space_delta.Scale(scale_from_viewport_to_screen_space);
1496
1497 // First project the scroll start and end points to local layer space to find
1498 // the scroll delta in layer coordinates.
1499 bool start_clipped, end_clipped;
1500 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta;
1501 gfx::PointF local_start_point =
[email protected]fa816c62013-03-18 04:24:211502 MathUtil::ProjectPoint(inverse_screen_space_transform,
[email protected]c1bb5af2013-03-13 19:06:271503 screen_space_point,
[email protected]fa816c62013-03-18 04:24:211504 &start_clipped);
[email protected]c1bb5af2013-03-13 19:06:271505 gfx::PointF local_end_point =
[email protected]fa816c62013-03-18 04:24:211506 MathUtil::ProjectPoint(inverse_screen_space_transform,
[email protected]c1bb5af2013-03-13 19:06:271507 screen_space_end_point,
[email protected]fa816c62013-03-18 04:24:211508 &end_clipped);
[email protected]c1bb5af2013-03-13 19:06:271509
1510 // In general scroll point coordinates should not get clipped.
1511 DCHECK(!start_clipped);
1512 DCHECK(!end_clipped);
1513 if (start_clipped || end_clipped)
1514 return gfx::Vector2dF();
1515
1516 // local_start_point and local_end_point are in content space but we want to
1517 // move them to layer space for scrolling.
1518 float width_scale = 1.f / layer_impl->contents_scale_x();
1519 float height_scale = 1.f / layer_impl->contents_scale_y();
1520 local_start_point.Scale(width_scale, height_scale);
1521 local_end_point.Scale(width_scale, height_scale);
1522
1523 // Apply the scroll delta.
1524 gfx::Vector2dF previous_delta = layer_impl->scroll_delta();
1525 layer_impl->ScrollBy(local_end_point - local_start_point);
1526
1527 // Get the end point in the layer's content space so we can apply its
1528 // ScreenSpaceTransform.
1529 gfx::PointF actual_local_end_point = local_start_point +
1530 layer_impl->scroll_delta() -
1531 previous_delta;
1532 gfx::PointF actual_local_content_end_point =
1533 gfx::ScalePoint(actual_local_end_point,
1534 1.f / width_scale,
1535 1.f / height_scale);
1536
1537 // Calculate the applied scroll delta in viewport space coordinates.
1538 gfx::PointF actual_screen_space_end_point =
[email protected]fa816c62013-03-18 04:24:211539 MathUtil::MapPoint(layer_impl->screen_space_transform(),
[email protected]c1bb5af2013-03-13 19:06:271540 actual_local_content_end_point,
[email protected]fa816c62013-03-18 04:24:211541 &end_clipped);
[email protected]c1bb5af2013-03-13 19:06:271542 DCHECK(!end_clipped);
1543 if (end_clipped)
1544 return gfx::Vector2dF();
1545 gfx::PointF actual_viewport_end_point =
1546 gfx::ScalePoint(actual_screen_space_end_point,
1547 1.f / scale_from_viewport_to_screen_space);
1548 return actual_viewport_end_point - viewport_point;
[email protected]94f206c12012-08-25 00:09:141549}
1550
[email protected]c1bb5af2013-03-13 19:06:271551static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl,
1552 gfx::Vector2dF local_delta) {
1553 gfx::Vector2dF previous_delta(layer_impl->scroll_delta());
1554 layer_impl->ScrollBy(local_delta);
1555 return layer_impl->scroll_delta() - previous_delta;
1556}
1557
1558bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
1559 gfx::Vector2dF scroll_delta) {
1560 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
1561 if (!CurrentlyScrollingLayer())
1562 return false;
1563
1564 gfx::Vector2dF pending_delta = scroll_delta;
1565 bool did_scroll = false;
[email protected]60b4d252013-03-23 18:49:421566 bool consume_by_top_controls = top_controls_manager_ &&
1567 (CurrentlyScrollingLayer() == RootScrollLayer() || scroll_delta.y() < 0);
[email protected]a91e4f82013-03-15 06:58:061568
[email protected]c1bb5af2013-03-13 19:06:271569 for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
1570 layer_impl;
1571 layer_impl = layer_impl->parent()) {
1572 if (!layer_impl->scrollable())
1573 continue;
1574
[email protected]60b4d252013-03-23 18:49:421575 // Only allow bubble scrolling when the scroll is in the direction to make
1576 // the top controls visible.
1577 if (consume_by_top_controls && layer_impl == RootScrollLayer()) {
1578 pending_delta = top_controls_manager_->ScrollBy(pending_delta);
1579 UpdateMaxScrollOffset();
1580 }
1581
[email protected]c1bb5af2013-03-13 19:06:271582 gfx::Vector2dF applied_delta;
[email protected]c1bb5af2013-03-13 19:06:271583 // Gesture events need to be transformed from viewport coordinates to local
1584 // layer coordinates so that the scrolling contents exactly follow the
1585 // user's finger. In contrast, wheel events represent a fixed amount of
1586 // scrolling so we can just apply them directly.
1587 if (!wheel_scrolling_) {
1588 float scale_from_viewport_to_screen_space = device_scale_factor_;
1589 applied_delta =
1590 ScrollLayerWithViewportSpaceDelta(layer_impl,
1591 scale_from_viewport_to_screen_space,
1592 viewport_point, pending_delta);
1593 } else {
1594 applied_delta = ScrollLayerWithLocalDelta(layer_impl, pending_delta);
[email protected]94f206c12012-08-25 00:09:141595 }
[email protected]94f206c12012-08-25 00:09:141596
[email protected]c1bb5af2013-03-13 19:06:271597 // If the layer wasn't able to move, try the next one in the hierarchy.
1598 float move_threshold_squared = 0.1f * 0.1f;
1599 if (applied_delta.LengthSquared() < move_threshold_squared) {
1600 if (should_bubble_scrolls_ || !did_lock_scrolling_layer_)
1601 continue;
1602 else
1603 break;
[email protected]94f206c12012-08-25 00:09:141604 }
[email protected]c1bb5af2013-03-13 19:06:271605 did_scroll = true;
1606 did_lock_scrolling_layer_ = true;
1607 if (!should_bubble_scrolls_) {
[email protected]0fc818e2013-03-18 06:45:201608 active_tree_->SetCurrentlyScrollingLayer(layer_impl);
[email protected]c1bb5af2013-03-13 19:06:271609 break;
[email protected]94f206c12012-08-25 00:09:141610 }
[email protected]94f206c12012-08-25 00:09:141611
[email protected]c1bb5af2013-03-13 19:06:271612 // If the applied delta is within 45 degrees of the input delta, bail out to
1613 // make it easier to scroll just one layer in one direction without
1614 // affecting any of its parents.
1615 float angle_threshold = 45;
[email protected]fa816c62013-03-18 04:24:211616 if (MathUtil::SmallestAngleBetweenVectors(
[email protected]c1bb5af2013-03-13 19:06:271617 applied_delta, pending_delta) < angle_threshold) {
1618 pending_delta = gfx::Vector2d();
1619 break;
[email protected]4a23c374c2012-12-08 08:38:551620 }
[email protected]c1bb5af2013-03-13 19:06:271621
1622 // Allow further movement only on an axis perpendicular to the direction in
1623 // which the layer moved.
1624 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
[email protected]fa816c62013-03-18 04:24:211625 pending_delta = MathUtil::ProjectVector(pending_delta, perpendicular_axis);
[email protected]c1bb5af2013-03-13 19:06:271626
1627 if (gfx::ToFlooredVector2d(pending_delta).IsZero())
1628 break;
1629 }
1630
[email protected]b7c4783f2013-03-15 23:11:421631 active_tree()->DidUpdateScroll();
[email protected]c1bb5af2013-03-13 19:06:271632 if (did_scroll) {
1633 client_->SetNeedsCommitOnImplThread();
1634 client_->SetNeedsRedrawOnImplThread();
1635 client_->RenewTreePriority();
1636 }
1637 return did_scroll;
[email protected]4a23c374c2012-12-08 08:38:551638}
1639
[email protected]be782f52013-03-23 21:36:141640// This implements scrolling by page as described here:
1641// http://msdn.microsoft.com/en-us/library/windows/desktop/ms645601(v=vs.85).aspx#_win32_The_Mouse_Wheel
1642// for events with WHEEL_PAGESCROLL set.
1643bool LayerTreeHostImpl::ScrollVerticallyByPage(
1644 gfx::Point viewport_point,
1645 WebKit::WebScrollbar::ScrollDirection direction) {
1646 DCHECK(wheel_scrolling_);
1647
1648 for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
1649 layer_impl;
1650 layer_impl = layer_impl->parent()) {
1651 if (!layer_impl->scrollable())
1652 continue;
1653
1654 if (!layer_impl->vertical_scrollbar_layer())
1655 continue;
1656
1657 float height = layer_impl->vertical_scrollbar_layer()->bounds().height();
1658
1659 // These magical values match WebKit and are designed to scroll nearly the
1660 // entire visible content height but leave a bit of overlap.
1661 float page = std::max(height * 0.875f, 1.f);
1662 if (direction == WebKit::WebScrollbar::ScrollBackward)
1663 page = -page;
1664
1665 gfx::Vector2dF delta = gfx::Vector2dF(0.f, page);
1666
1667 gfx::Vector2dF applied_delta = ScrollLayerWithLocalDelta(layer_impl, delta);
1668
1669 if (!applied_delta.IsZero()) {
1670 active_tree()->DidUpdateScroll();
1671 client_->SetNeedsCommitOnImplThread();
1672 client_->SetNeedsRedrawOnImplThread();
1673 client_->RenewTreePriority();
1674 return true;
1675 }
1676
1677 active_tree_->SetCurrentlyScrollingLayer(layer_impl);
1678 }
1679
1680 return false;
1681}
1682
[email protected]c1bb5af2013-03-13 19:06:271683void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() {
1684 active_tree_->ClearCurrentlyScrollingLayer();
1685 did_lock_scrolling_layer_ = false;
[email protected]94f206c12012-08-25 00:09:141686}
1687
[email protected]c1bb5af2013-03-13 19:06:271688void LayerTreeHostImpl::ScrollEnd() {
1689 if (top_controls_manager_)
1690 top_controls_manager_->ScrollEnd();
1691 ClearCurrentlyScrollingLayer();
[email protected]b7c4783f2013-03-15 23:11:421692 active_tree()->DidEndScroll();
[email protected]0fc818e2013-03-18 06:45:201693 StartScrollbarAnimation(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141694}
1695
[email protected]c1bb5af2013-03-13 19:06:271696void LayerTreeHostImpl::PinchGestureBegin() {
1697 pinch_gesture_active_ = true;
1698 previous_pinch_anchor_ = gfx::Point();
1699 client_->RenewTreePriority();
[email protected]94f206c12012-08-25 00:09:141700}
1701
[email protected]c1bb5af2013-03-13 19:06:271702void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
1703 gfx::Point anchor) {
1704 TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
[email protected]d3afa112012-12-08 06:24:281705
[email protected]c1bb5af2013-03-13 19:06:271706 if (!RootScrollLayer())
1707 return;
[email protected]d3afa112012-12-08 06:24:281708
[email protected]c1bb5af2013-03-13 19:06:271709 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1710 // position over the course of the magnify.
1711 float page_scale_delta = active_tree_->page_scale_delta();
1712 gfx::PointF previous_scale_anchor =
1713 gfx::ScalePoint(anchor, 1.f / page_scale_delta);
1714 active_tree_->SetPageScaleDelta(page_scale_delta * magnify_delta);
1715 page_scale_delta = active_tree_->page_scale_delta();
1716 gfx::PointF new_scale_anchor =
1717 gfx::ScalePoint(anchor, 1.f / page_scale_delta);
1718 gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor;
1719
1720 previous_pinch_anchor_ = anchor;
1721
1722 move.Scale(1 / active_tree_->page_scale_factor());
1723
1724 RootScrollLayer()->ScrollBy(move);
1725
[email protected]c1bb5af2013-03-13 19:06:271726 client_->SetNeedsCommitOnImplThread();
1727 client_->SetNeedsRedrawOnImplThread();
1728 client_->RenewTreePriority();
[email protected]d3afa112012-12-08 06:24:281729}
1730
[email protected]c1bb5af2013-03-13 19:06:271731void LayerTreeHostImpl::PinchGestureEnd() {
1732 pinch_gesture_active_ = false;
[email protected]c1bb5af2013-03-13 19:06:271733 client_->SetNeedsCommitOnImplThread();
[email protected]94f206c12012-08-25 00:09:141734}
1735
[email protected]c1bb5af2013-03-13 19:06:271736static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info,
1737 LayerImpl* layer_impl) {
1738 if (!layer_impl)
1739 return;
[email protected]94f206c12012-08-25 00:09:141740
[email protected]c1bb5af2013-03-13 19:06:271741 gfx::Vector2d scroll_delta =
1742 gfx::ToFlooredVector2d(layer_impl->scroll_delta());
1743 if (!scroll_delta.IsZero()) {
1744 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]6ba914122013-03-22 16:26:391745 scroll.layer_id = layer_impl->id();
1746 scroll.scroll_delta = scroll_delta;
[email protected]c1bb5af2013-03-13 19:06:271747 scroll_info->scrolls.push_back(scroll);
1748 layer_impl->SetSentScrollDelta(scroll_delta);
1749 }
[email protected]94f206c12012-08-25 00:09:141750
[email protected]c1bb5af2013-03-13 19:06:271751 for (size_t i = 0; i < layer_impl->children().size(); ++i)
1752 CollectScrollDeltas(scroll_info, layer_impl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141753}
1754
[email protected]c1bb5af2013-03-13 19:06:271755scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
1756 scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet());
[email protected]362f1e8b2013-01-21 16:54:301757
[email protected]c1bb5af2013-03-13 19:06:271758 CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer());
[email protected]6ba914122013-03-22 16:26:391759 scroll_info->page_scale_delta = active_tree_->page_scale_delta();
1760 active_tree_->set_sent_page_scale_delta(scroll_info->page_scale_delta);
[email protected]362f1e8b2013-01-21 16:54:301761
[email protected]c1bb5af2013-03-13 19:06:271762 return scroll_info.Pass();
[email protected]362f1e8b2013-01-21 16:54:301763}
1764
[email protected]c1bb5af2013-03-13 19:06:271765void LayerTreeHostImpl::SetFullRootLayerDamage() {
1766 if (active_tree_->root_layer()) {
1767 RenderSurfaceImpl* render_surface =
1768 active_tree_->root_layer()->render_surface();
1769 if (render_surface)
1770 render_surface->damage_tracker()->ForceFullDamageNextUpdate();
1771 }
[email protected]829ad972013-01-28 23:36:101772}
1773
[email protected]c1bb5af2013-03-13 19:06:271774void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
1775 if (!page_scale_animation_ || !RootScrollLayer())
1776 return;
1777
1778 double monotonic_time = (time - base::TimeTicks()).InSecondsF();
1779 gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() +
1780 RootScrollLayer()->scroll_delta();
1781
1782 active_tree_->SetPageScaleDelta(
1783 page_scale_animation_->PageScaleFactorAtTime(monotonic_time) /
1784 active_tree_->page_scale_factor());
1785 gfx::Vector2dF next_scroll =
1786 page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
1787
1788 RootScrollLayer()->ScrollBy(next_scroll - scroll_total);
1789 client_->SetNeedsRedrawOnImplThread();
1790
1791 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
1792 page_scale_animation_.reset();
1793 client_->SetNeedsCommitOnImplThread();
1794 client_->RenewTreePriority();
1795 }
[email protected]829ad972013-01-28 23:36:101796}
1797
[email protected]ffb2720f2013-03-15 19:18:371798void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) {
1799 if (!top_controls_manager_ || !RootScrollLayer())
1800 return;
1801 gfx::Vector2dF scroll = top_controls_manager_->Animate(time);
1802 UpdateMaxScrollOffset();
1803 RootScrollLayer()->ScrollBy(gfx::ScaleVector2d(
1804 scroll, 1.f / active_tree_->total_page_scale_factor()));
1805}
1806
[email protected]c1bb5af2013-03-13 19:06:271807void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time,
1808 base::Time wall_clock_time) {
[email protected]8e0176d2013-03-21 03:14:521809 if (!settings_.accelerated_animation_enabled ||
[email protected]c1bb5af2013-03-13 19:06:271810 animation_registrar_->active_animation_controllers().empty() ||
1811 !active_tree_->root_layer())
1812 return;
1813
1814 TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers");
1815
1816 last_animation_time_ = wall_clock_time;
1817 double monotonic_seconds = (monotonic_time - base::TimeTicks()).InSecondsF();
1818
1819 AnimationRegistrar::AnimationControllerMap copy =
1820 animation_registrar_->active_animation_controllers();
1821 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1822 iter != copy.end();
1823 ++iter)
1824 (*iter).second->Animate(monotonic_seconds);
1825
1826 client_->SetNeedsRedrawOnImplThread();
[email protected]131a0c22013-02-12 18:31:081827}
1828
[email protected]3d9f7432013-04-06 00:35:181829void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
[email protected]8e0176d2013-03-21 03:14:521830 if (!settings_.accelerated_animation_enabled ||
[email protected]c1bb5af2013-03-13 19:06:271831 animation_registrar_->active_animation_controllers().empty() ||
1832 !active_tree_->root_layer())
1833 return;
1834
1835 TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState");
1836 scoped_ptr<AnimationEventsVector> events =
1837 make_scoped_ptr(new AnimationEventsVector);
1838 AnimationRegistrar::AnimationControllerMap copy =
1839 animation_registrar_->active_animation_controllers();
1840 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1841 iter != copy.end();
1842 ++iter)
[email protected]3d9f7432013-04-06 00:35:181843 (*iter).second->UpdateState(start_ready_animations, events.get());
[email protected]c1bb5af2013-03-13 19:06:271844
1845 if (!events->empty()) {
1846 client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass(),
1847 last_animation_time_);
1848 }
[email protected]131a0c22013-02-12 18:31:081849}
1850
[email protected]c1bb5af2013-03-13 19:06:271851base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const {
1852 return base::TimeDelta::FromSeconds(1);
1853}
1854
1855void LayerTreeHostImpl::SendDidLoseOutputSurfaceRecursive(LayerImpl* current) {
1856 DCHECK(current);
1857 current->DidLoseOutputSurface();
1858 if (current->mask_layer())
1859 SendDidLoseOutputSurfaceRecursive(current->mask_layer());
1860 if (current->replica_layer())
1861 SendDidLoseOutputSurfaceRecursive(current->replica_layer());
1862 for (size_t i = 0; i < current->children().size(); ++i)
1863 SendDidLoseOutputSurfaceRecursive(current->children()[i]);
1864}
1865
1866void LayerTreeHostImpl::ClearRenderSurfaces() {
1867 active_tree_->ClearRenderSurfaces();
1868 if (pending_tree_)
1869 pending_tree_->ClearRenderSurfaces();
1870}
1871
1872std::string LayerTreeHostImpl::LayerTreeAsText() const {
1873 std::string str;
1874 if (active_tree_->root_layer()) {
1875 str = active_tree_->root_layer()->LayerTreeAsText();
1876 str += "RenderSurfaces:\n";
1877 DumpRenderSurfaces(&str, 1, active_tree_->root_layer());
1878 }
1879 return str;
1880}
1881
1882std::string LayerTreeHostImpl::LayerTreeAsJson() const {
1883 std::string str;
1884 if (active_tree_->root_layer()) {
1885 scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson());
1886 base::JSONWriter::WriteWithOptions(
1887 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str);
1888 }
1889 return str;
1890}
1891
1892void LayerTreeHostImpl::DumpRenderSurfaces(std::string* str,
1893 int indent,
1894 const LayerImpl* layer) const {
1895 if (layer->render_surface())
1896 layer->render_surface()->DumpSurface(str, indent);
1897
1898 for (size_t i = 0; i < layer->children().size(); ++i)
1899 DumpRenderSurfaces(str, indent, layer->children()[i]);
1900}
1901
1902int LayerTreeHostImpl::SourceAnimationFrameNumber() const {
[email protected]9e3594522013-03-18 00:57:361903 return fps_counter_->current_frame_number();
[email protected]c1bb5af2013-03-13 19:06:271904}
1905
[email protected]c1bb5af2013-03-13 19:06:271906void LayerTreeHostImpl::SendManagedMemoryStats(
1907 size_t memory_visible_bytes,
1908 size_t memory_visible_and_nearby_bytes,
1909 size_t memory_use_bytes) {
1910 if (!renderer_)
1911 return;
1912
1913 // Round the numbers being sent up to the next 8MB, to throttle the rate
1914 // at which we spam the GPU process.
1915 static const size_t rounding_step = 8 * 1024 * 1024;
1916 memory_visible_bytes = RoundUp(memory_visible_bytes, rounding_step);
1917 memory_visible_and_nearby_bytes = RoundUp(memory_visible_and_nearby_bytes,
1918 rounding_step);
1919 memory_use_bytes = RoundUp(memory_use_bytes, rounding_step);
1920 if (last_sent_memory_visible_bytes_ == memory_visible_bytes &&
1921 last_sent_memory_visible_and_nearby_bytes_ ==
1922 memory_visible_and_nearby_bytes &&
1923 last_sent_memory_use_bytes_ == memory_use_bytes) {
1924 return;
1925 }
1926 last_sent_memory_visible_bytes_ = memory_visible_bytes;
1927 last_sent_memory_visible_and_nearby_bytes_ = memory_visible_and_nearby_bytes;
1928 last_sent_memory_use_bytes_ = memory_use_bytes;
1929
1930 renderer_->SendManagedMemoryStats(last_sent_memory_visible_bytes_,
1931 last_sent_memory_visible_and_nearby_bytes_,
1932 last_sent_memory_use_bytes_);
1933}
1934
1935void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) {
1936 AnimateScrollbarsRecursive(active_tree_->root_layer(), time);
1937}
1938
1939void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer,
1940 base::TimeTicks time) {
1941 if (!layer)
1942 return;
1943
1944 ScrollbarAnimationController* scrollbar_controller =
1945 layer->scrollbar_animation_controller();
[email protected]6bc09e82013-03-19 03:48:351946 if (scrollbar_controller && scrollbar_controller->Animate(time)) {
[email protected]0fc818e2013-03-18 06:45:201947 TRACE_EVENT_INSTANT0(
[email protected]c76faea2013-03-26 07:42:421948 "cc", "LayerTreeHostImpl::SetNeedsRedraw due to AnimateScrollbars",
1949 TRACE_EVENT_SCOPE_THREAD);
[email protected]c1bb5af2013-03-13 19:06:271950 client_->SetNeedsRedrawOnImplThread();
[email protected]0fc818e2013-03-18 06:45:201951 }
[email protected]c1bb5af2013-03-13 19:06:271952
1953 for (size_t i = 0; i < layer->children().size(); ++i)
1954 AnimateScrollbarsRecursive(layer->children()[i], time);
1955}
1956
[email protected]0fc818e2013-03-18 06:45:201957void LayerTreeHostImpl::StartScrollbarAnimation(base::TimeTicks time) {
1958 TRACE_EVENT0("cc", "LayerTreeHostImpl::StartScrollbarAnimation");
1959 StartScrollbarAnimationRecursive(RootLayer(), time);
1960}
1961
1962void LayerTreeHostImpl::StartScrollbarAnimationRecursive(LayerImpl* layer,
1963 base::TimeTicks time) {
1964 if (!layer)
1965 return;
1966
1967 ScrollbarAnimationController* scrollbar_controller =
1968 layer->scrollbar_animation_controller();
[email protected]6bc09e82013-03-19 03:48:351969 if (scrollbar_controller && scrollbar_controller->IsAnimating()) {
1970 base::TimeDelta delay = scrollbar_controller->DelayBeforeStart(time);
[email protected]0fc818e2013-03-18 06:45:201971 if (delay > base::TimeDelta())
1972 client_->RequestScrollbarAnimationOnImplThread(delay);
[email protected]6bc09e82013-03-19 03:48:351973 else if (scrollbar_controller->Animate(time))
[email protected]0fc818e2013-03-18 06:45:201974 client_->SetNeedsRedrawOnImplThread();
1975 }
1976
1977 for (size_t i = 0; i < layer->children().size(); ++i)
1978 StartScrollbarAnimationRecursive(layer->children()[i], time);
1979}
1980
[email protected]c1bb5af2013-03-13 19:06:271981void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
1982 if (!tile_manager_)
1983 return;
1984
1985 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
1986 if (new_state.tree_priority == priority)
1987 return;
1988
1989 new_state.tree_priority = priority;
1990 tile_manager_->SetGlobalState(new_state);
1991}
1992
1993void LayerTreeHostImpl::BeginNextFrame() {
1994 current_frame_time_ = base::TimeTicks();
1995}
1996
1997base::TimeTicks LayerTreeHostImpl::CurrentFrameTime() {
1998 if (current_frame_time_.is_null())
1999 current_frame_time_ = base::TimeTicks::Now();
2000 return current_frame_time_;
2001}
2002
2003scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const {
2004 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
2005 state->Set("activation_state", ActivationStateAsValue().release());
2006 state->Set("frame_state", FrameStateAsValue().release());
2007 return state.PassAs<base::Value>();
2008}
2009
2010scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const {
2011 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
[email protected]7d3cbc92013-03-18 22:33:042012 state->SetString("lthi_id", base::StringPrintf("%p", this));
[email protected]c1bb5af2013-03-13 19:06:272013 state->SetBoolean("visible_resources_ready",
2014 pending_tree_->AreVisibleResourcesReady());
2015 state->Set("tile_manager", tile_manager_->BasicStateAsValue().release());
2016 return state.PassAs<base::Value>();
2017}
2018
2019scoped_ptr<base::Value> LayerTreeHostImpl::FrameStateAsValue() const {
2020 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
[email protected]7d3cbc92013-03-18 22:33:042021 state->SetString("lthi_id", base::StringPrintf("%p", this));
[email protected]c1bb5af2013-03-13 19:06:272022 state->Set("device_viewport_size",
[email protected]fa816c62013-03-18 04:24:212023 MathUtil::AsValue(device_viewport_size_).release());
[email protected]c1bb5af2013-03-13 19:06:272024 if (tile_manager_)
2025 state->Set("tiles", tile_manager_->AllTilesAsValue().release());
2026 state->Set("active_tree", active_tree_->AsValue().release());
2027 return state.PassAs<base::Value>();
[email protected]131a0c22013-02-12 18:31:082028}
2029
[email protected]b9dcf43a2013-01-09 00:15:292030// static
[email protected]c1bb5af2013-03-13 19:06:272031LayerImpl* LayerTreeHostImpl::GetNonCompositedContentLayerRecursive(
2032 LayerImpl* layer) {
2033 if (!layer)
[email protected]b9dcf43a2013-01-09 00:15:292034 return NULL;
[email protected]c1bb5af2013-03-13 19:06:272035
2036 if (layer->DrawsContent())
2037 return layer;
2038
[email protected]50761e92013-03-29 20:51:282039 for (LayerImplList::const_iterator it = layer->children().begin();
[email protected]c1bb5af2013-03-13 19:06:272040 it != layer->children().end(); ++it) {
2041 LayerImpl* nccr = GetNonCompositedContentLayerRecursive(*it);
2042 if (nccr)
2043 return nccr;
2044 }
2045
2046 return NULL;
[email protected]b9dcf43a2013-01-09 00:15:292047}
2048
[email protected]c1bb5af2013-03-13 19:06:272049skia::RefPtr<SkPicture> LayerTreeHostImpl::CapturePicture() {
2050 LayerTreeImpl* tree =
2051 pending_tree_ ? pending_tree_.get() : active_tree_.get();
2052 LayerImpl* layer = GetNonCompositedContentLayerRecursive(tree->root_layer());
2053 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>();
[email protected]b9dcf43a2013-01-09 00:15:292054}
2055
[email protected]c1bb5af2013-03-13 19:06:272056void LayerTreeHostImpl::SetDebugState(const LayerTreeDebugState& debug_state) {
[email protected]846f455b2013-03-18 19:07:412057 if (debug_state_.continuous_painting != debug_state.continuous_painting)
[email protected]c1bb5af2013-03-13 19:06:272058 paint_time_counter_->ClearHistory();
[email protected]652cf132013-02-15 21:53:242059
[email protected]c1bb5af2013-03-13 19:06:272060 debug_state_ = debug_state;
[email protected]d0d12192013-02-08 19:02:022061}
2062
[email protected]d3143c732012-10-05 19:17:592063} // namespace cc