Add signalSyncPoint to the WebGraphicsContext3D command buffer impls.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl.cc
bloba96608952e5dde5824227e42ee3184b2f741a01e
1 // 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.
5 #include "cc/trees/layer_tree_host_impl.h"
7 #include <algorithm>
9 #include "base/basictypes.h"
10 #include "base/debug/trace_event.h"
11 #include "base/json/json_writer.h"
12 #include "base/metrics/histogram.h"
13 #include "base/stl_util.h"
14 #include "base/stringprintf.h"
15 #include "cc/animation/scrollbar_animation_controller.h"
16 #include "cc/animation/timing_function.h"
17 #include "cc/base/math_util.h"
18 #include "cc/base/util.h"
19 #include "cc/debug/debug_rect_history.h"
20 #include "cc/debug/frame_rate_counter.h"
21 #include "cc/debug/overdraw_metrics.h"
22 #include "cc/debug/paint_time_counter.h"
23 #include "cc/debug/rendering_stats_instrumentation.h"
24 #include "cc/input/page_scale_animation.h"
25 #include "cc/input/top_controls_manager.h"
26 #include "cc/layers/append_quads_data.h"
27 #include "cc/layers/heads_up_display_layer_impl.h"
28 #include "cc/layers/layer_impl.h"
29 #include "cc/layers/layer_iterator.h"
30 #include "cc/layers/render_surface_impl.h"
31 #include "cc/layers/scrollbar_layer_impl.h"
32 #include "cc/output/compositor_frame_metadata.h"
33 #include "cc/output/delegating_renderer.h"
34 #include "cc/output/gl_renderer.h"
35 #include "cc/output/software_renderer.h"
36 #include "cc/quads/render_pass_draw_quad.h"
37 #include "cc/quads/shared_quad_state.h"
38 #include "cc/quads/solid_color_draw_quad.h"
39 #include "cc/resources/memory_history.h"
40 #include "cc/resources/picture_layer_tiling.h"
41 #include "cc/resources/prioritized_resource_manager.h"
42 #include "cc/scheduler/delay_based_time_source.h"
43 #include "cc/scheduler/texture_uploader.h"
44 #include "cc/trees/damage_tracker.h"
45 #include "cc/trees/layer_tree_host.h"
46 #include "cc/trees/layer_tree_host_common.h"
47 #include "cc/trees/layer_tree_impl.h"
48 #include "cc/trees/quad_culler.h"
49 #include "cc/trees/single_thread_proxy.h"
50 #include "cc/trees/tree_synchronizer.h"
51 #include "ui/gfx/size_conversions.h"
52 #include "ui/gfx/vector2d_conversions.h"
54 namespace {
56 void DidVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) {
57 if (visible) {
58 TRACE_EVENT_ASYNC_BEGIN1("webkit",
59 "LayerTreeHostImpl::SetVisible",
60 id,
61 "LayerTreeHostImpl",
62 id);
63 return;
66 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::SetVisible", id);
69 std::string ValueToString(scoped_ptr<base::Value> value) {
70 std::string str;
71 base::JSONWriter::Write(value.get(), &str);
72 return str;
75 } // namespace
77 namespace cc {
79 class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
80 public:
81 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create(
82 LayerTreeHostImpl* layer_tree_host_impl,
83 scoped_refptr<DelayBasedTimeSource> time_source) {
84 return make_scoped_ptr(
85 new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl,
86 time_source));
88 virtual ~LayerTreeHostImplTimeSourceAdapter() {
89 time_source_->SetClient(NULL);
90 time_source_->SetActive(false);
93 virtual void OnTimerTick() OVERRIDE {
94 // In single threaded mode we attempt to simulate changing the current
95 // thread by maintaining a fake thread id. When we switch from one
96 // thread to another, we construct DebugScopedSetXXXThread objects that
97 // update the thread id. This lets DCHECKS that ensure we're on the
98 // right thread to work correctly in single threaded mode. The problem
99 // here is that the timer tasks are run via the message loop, and when
100 // they run, we've had no chance to construct a DebugScopedSetXXXThread
101 // object. The result is that we report that we're running on the main
102 // thread. In multi-threaded mode, this timer is run on the compositor
103 // thread, so to keep this consistent in single-threaded mode, we'll
104 // construct a DebugScopedSetImplThread object. There is no need to do
105 // this in multi-threaded mode since the real thread id's will be
106 // correct. In fact, setting fake thread id's interferes with the real
107 // thread id's and causes breakage.
108 scoped_ptr<DebugScopedSetImplThread> set_impl_thread;
109 if (!layer_tree_host_impl_->proxy()->HasImplThread()) {
110 set_impl_thread.reset(
111 new DebugScopedSetImplThread(layer_tree_host_impl_->proxy()));
114 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
115 layer_tree_host_impl_->Animate(
116 layer_tree_host_impl_->CurrentFrameTimeTicks(),
117 layer_tree_host_impl_->CurrentFrameTime());
118 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(true);
119 bool start_ready_animations = true;
120 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
121 layer_tree_host_impl_->BeginNextFrame();
124 void SetActive(bool active) {
125 if (active != time_source_->Active())
126 time_source_->SetActive(active);
129 private:
130 LayerTreeHostImplTimeSourceAdapter(
131 LayerTreeHostImpl* layer_tree_host_impl,
132 scoped_refptr<DelayBasedTimeSource> time_source)
133 : layer_tree_host_impl_(layer_tree_host_impl),
134 time_source_(time_source) {
135 time_source_->SetClient(this);
138 LayerTreeHostImpl* layer_tree_host_impl_;
139 scoped_refptr<DelayBasedTimeSource> time_source_;
141 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
144 LayerTreeHostImpl::FrameData::FrameData()
145 : contains_incomplete_tile(false), has_no_damage(false) {}
147 LayerTreeHostImpl::FrameData::~FrameData() {}
149 scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
150 const LayerTreeSettings& settings,
151 LayerTreeHostImplClient* client,
152 Proxy* proxy,
153 RenderingStatsInstrumentation* rendering_stats_instrumentation) {
154 return make_scoped_ptr(
155 new LayerTreeHostImpl(settings,
156 client,
157 proxy,
158 rendering_stats_instrumentation));
161 LayerTreeHostImpl::LayerTreeHostImpl(
162 const LayerTreeSettings& settings,
163 LayerTreeHostImplClient* client,
164 Proxy* proxy,
165 RenderingStatsInstrumentation* rendering_stats_instrumentation)
166 : client_(client),
167 proxy_(proxy),
168 did_lock_scrolling_layer_(false),
169 should_bubble_scrolls_(false),
170 wheel_scrolling_(false),
171 settings_(settings),
172 overdraw_bottom_height_(0.f),
173 device_scale_factor_(1.f),
174 visible_(true),
175 managed_memory_policy_(
176 PrioritizedResourceManager::DefaultMemoryAllocationLimit(),
177 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
179 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING),
180 pinch_gesture_active_(false),
181 fps_counter_(FrameRateCounter::Create(proxy_->HasImplThread())),
182 paint_time_counter_(PaintTimeCounter::Create()),
183 memory_history_(MemoryHistory::Create()),
184 debug_rect_history_(DebugRectHistory::Create()),
185 max_memory_needed_bytes_(0),
186 last_sent_memory_visible_bytes_(0),
187 last_sent_memory_visible_and_nearby_bytes_(0),
188 last_sent_memory_use_bytes_(0),
189 animation_registrar_(AnimationRegistrar::Create()),
190 rendering_stats_instrumentation_(rendering_stats_instrumentation) {
191 DCHECK(proxy_->IsImplThread());
192 DidVisibilityChange(this, visible_);
194 SetDebugState(settings.initial_debug_state);
196 if (settings.calculate_top_controls_position) {
197 top_controls_manager_ =
198 TopControlsManager::Create(this,
199 settings.top_controls_height,
200 settings.top_controls_show_threshold,
201 settings.top_controls_hide_threshold);
204 SetDebugState(settings.initial_debug_state);
206 // LTHI always has an active tree.
207 active_tree_ = LayerTreeImpl::create(this);
210 LayerTreeHostImpl::~LayerTreeHostImpl() {
211 DCHECK(proxy_->IsImplThread());
212 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
214 if (active_tree_->root_layer()) {
215 ClearRenderSurfaces();
216 // The layer trees must be destroyed before the layer tree host. We've
217 // made a contract with our animation controllers that the registrar
218 // will outlive them, and we must make good.
219 recycle_tree_.reset();
220 pending_tree_.reset();
221 active_tree_.reset();
225 void LayerTreeHostImpl::BeginCommit() {}
227 void LayerTreeHostImpl::CommitComplete() {
228 TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete");
230 // Impl-side painting needs an update immediately post-commit to have the
231 // opportunity to create tilings. Other paths can call UpdateDrawProperties
232 // more lazily when needed prior to drawing.
233 if (settings_.impl_side_painting) {
234 pending_tree_->set_needs_update_draw_properties();
235 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE);
236 } else {
237 active_tree_->set_needs_update_draw_properties();
240 client_->SendManagedMemoryStats();
243 bool LayerTreeHostImpl::CanDraw() {
244 // Note: If you are changing this function or any other function that might
245 // affect the result of CanDraw, make sure to call
246 // client_->OnCanDrawStateChanged in the proper places and update the
247 // NotifyIfCanDrawChanged test.
249 if (!active_tree_->root_layer()) {
250 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no root layer",
251 TRACE_EVENT_SCOPE_THREAD);
252 return false;
254 if (device_viewport_size_.IsEmpty()) {
255 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport",
256 TRACE_EVENT_SCOPE_THREAD);
257 return false;
259 if (active_tree_->ViewportSizeInvalid()) {
260 TRACE_EVENT_INSTANT0(
261 "cc", "LayerTreeHostImpl::CanDraw viewport size recently changed",
262 TRACE_EVENT_SCOPE_THREAD);
263 return false;
265 if (!renderer_) {
266 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no renderer",
267 TRACE_EVENT_SCOPE_THREAD);
268 return false;
270 if (active_tree_->ContentsTexturesPurged()) {
271 TRACE_EVENT_INSTANT0(
272 "cc", "LayerTreeHostImpl::CanDraw contents textures purged",
273 TRACE_EVENT_SCOPE_THREAD);
274 return false;
276 return true;
279 void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time,
280 base::Time wall_clock_time) {
281 AnimatePageScale(monotonic_time);
282 AnimateLayers(monotonic_time, wall_clock_time);
283 AnimateScrollbars(monotonic_time);
284 AnimateTopControls(monotonic_time);
287 void LayerTreeHostImpl::ManageTiles() {
288 DCHECK(tile_manager_);
289 tile_manager_->ManageTiles();
291 size_t memory_required_bytes;
292 size_t memory_nice_to_have_bytes;
293 size_t memory_used_bytes;
294 tile_manager_->GetMemoryStats(&memory_required_bytes,
295 &memory_nice_to_have_bytes,
296 &memory_used_bytes);
297 SendManagedMemoryStats(memory_required_bytes,
298 memory_nice_to_have_bytes,
299 memory_used_bytes);
302 void LayerTreeHostImpl::SetAnticipatedDrawTime(base::TimeTicks time) {
303 if (tile_manager_)
304 tile_manager_->SetAnticipatedDrawTime(time);
307 void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset,
308 bool anchor_point,
309 float page_scale,
310 base::TimeTicks start_time,
311 base::TimeDelta duration) {
312 if (!RootScrollLayer())
313 return;
315 gfx::Vector2dF scroll_total =
316 RootScrollLayer()->scroll_offset() + RootScrollLayer()->scroll_delta();
317 gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize();
318 gfx::SizeF viewport_size = VisibleViewportSize();
320 double start_time_seconds = (start_time - base::TimeTicks()).InSecondsF();
322 // Easing constants experimentally determined.
323 scoped_ptr<TimingFunction> timing_function =
324 CubicBezierTimingFunction::Create(.8, 0, .3, .9).PassAs<TimingFunction>();
326 page_scale_animation_ =
327 PageScaleAnimation::Create(scroll_total,
328 active_tree_->total_page_scale_factor(),
329 viewport_size,
330 scaled_scrollable_size,
331 start_time_seconds,
332 timing_function.Pass());
334 if (anchor_point) {
335 gfx::Vector2dF anchor(target_offset);
336 page_scale_animation_->ZoomWithAnchor(anchor,
337 page_scale,
338 duration.InSecondsF());
339 } else {
340 gfx::Vector2dF scaled_target_offset = target_offset;
341 page_scale_animation_->ZoomTo(scaled_target_offset,
342 page_scale,
343 duration.InSecondsF());
346 client_->SetNeedsRedrawOnImplThread();
347 client_->SetNeedsCommitOnImplThread();
348 client_->RenewTreePriority();
351 void LayerTreeHostImpl::ScheduleAnimation() {
352 client_->SetNeedsRedrawOnImplThread();
355 bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) {
356 if (!EnsureRenderSurfaceLayerList())
357 return false;
359 gfx::PointF device_viewport_point =
360 gfx::ScalePoint(viewport_point, device_scale_factor_);
362 // First find out which layer was hit from the saved list of visible layers
363 // in the most recent frame.
364 LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
365 device_viewport_point,
366 active_tree_->RenderSurfaceLayerList());
368 // Walk up the hierarchy and look for a layer with a touch event handler
369 // region that the given point hits.
370 for (; layer_impl; layer_impl = layer_impl->parent()) {
371 if (LayerTreeHostCommon::LayerHasTouchEventHandlersAt(device_viewport_point,
372 layer_impl))
373 return true;
376 return false;
379 void LayerTreeHostImpl::DidReceiveLastInputEventForVSync(
380 base::TimeTicks frame_time) {
381 client_->DidReceiveLastInputEventForVSync(frame_time);
384 void LayerTreeHostImpl::TrackDamageForAllSurfaces(
385 LayerImpl* root_draw_layer,
386 const LayerImplList& render_surface_layer_list) {
387 // For now, we use damage tracking to compute a global scissor. To do this, we
388 // must compute all damage tracking before drawing anything, so that we know
389 // the root damage rect. The root damage rect is then used to scissor each
390 // surface.
392 for (int surface_index = render_surface_layer_list.size() - 1;
393 surface_index >= 0;
394 --surface_index) {
395 LayerImpl* render_surface_layer = render_surface_layer_list[surface_index];
396 RenderSurfaceImpl* render_surface = render_surface_layer->render_surface();
397 DCHECK(render_surface);
398 render_surface->damage_tracker()->UpdateDamageTrackingState(
399 render_surface->layer_list(),
400 render_surface_layer->id(),
401 render_surface->SurfacePropertyChangedOnlyFromDescendant(),
402 render_surface->content_rect(),
403 render_surface_layer->mask_layer(),
404 render_surface_layer->filters(),
405 render_surface_layer->filter().get());
409 void LayerTreeHostImpl::FrameData::AppendRenderPass(
410 scoped_ptr<RenderPass> render_pass) {
411 render_passes_by_id[render_pass->id] = render_pass.get();
412 render_passes.push_back(render_pass.Pass());
415 static void AppendQuadsForLayer(RenderPass* target_render_pass,
416 LayerImpl* layer,
417 const OcclusionTrackerImpl& occlusion_tracker,
418 AppendQuadsData* append_quads_data) {
419 bool for_surface = false;
420 QuadCuller quad_culler(&target_render_pass->quad_list,
421 &target_render_pass->shared_quad_state_list,
422 layer,
423 occlusion_tracker,
424 layer->ShowDebugBorders(),
425 for_surface);
426 layer->AppendQuads(&quad_culler, append_quads_data);
429 static void AppendQuadsForRenderSurfaceLayer(
430 RenderPass* target_render_pass,
431 LayerImpl* layer,
432 const RenderPass* contributing_render_pass,
433 const OcclusionTrackerImpl& occlusion_tracker,
434 AppendQuadsData* append_quads_data) {
435 bool for_surface = true;
436 QuadCuller quad_culler(&target_render_pass->quad_list,
437 &target_render_pass->shared_quad_state_list,
438 layer,
439 occlusion_tracker,
440 layer->ShowDebugBorders(),
441 for_surface);
443 bool is_replica = false;
444 layer->render_surface()->AppendQuads(&quad_culler,
445 append_quads_data,
446 is_replica,
447 contributing_render_pass->id);
449 // Add replica after the surface so that it appears below the surface.
450 if (layer->has_replica()) {
451 is_replica = true;
452 layer->render_surface()->AppendQuads(&quad_culler,
453 append_quads_data,
454 is_replica,
455 contributing_render_pass->id);
459 static void AppendQuadsToFillScreen(
460 RenderPass* target_render_pass,
461 LayerImpl* root_layer,
462 SkColor screen_background_color,
463 const OcclusionTrackerImpl& occlusion_tracker) {
464 if (!root_layer || !SkColorGetA(screen_background_color))
465 return;
467 Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen();
468 if (fill_region.IsEmpty())
469 return;
471 bool for_surface = false;
472 QuadCuller quad_culler(&target_render_pass->quad_list,
473 &target_render_pass->shared_quad_state_list,
474 root_layer,
475 occlusion_tracker,
476 root_layer->ShowDebugBorders(),
477 for_surface);
479 // Manually create the quad state for the gutter quads, as the root layer
480 // doesn't have any bounds and so can't generate this itself.
481 // TODO(danakj): Make the gutter quads generated by the solid color layer
482 // (make it smarter about generating quads to fill unoccluded areas).
484 gfx::Rect root_target_rect = root_layer->render_surface()->content_rect();
485 float opacity = 1.f;
486 SharedQuadState* shared_quad_state =
487 quad_culler.UseSharedQuadState(SharedQuadState::Create());
488 shared_quad_state->SetAll(root_layer->draw_transform(),
489 root_target_rect.size(),
490 root_target_rect,
491 root_target_rect,
492 false,
493 opacity);
495 AppendQuadsData append_quads_data;
497 gfx::Transform transform_to_layer_space(gfx::Transform::kSkipInitialization);
498 bool did_invert = root_layer->screen_space_transform().GetInverse(
499 &transform_to_layer_space);
500 DCHECK(did_invert);
501 for (Region::Iterator fill_rects(fill_region);
502 fill_rects.has_rect();
503 fill_rects.next()) {
504 // The root layer transform is composed of translations and scales only,
505 // no perspective, so mapping is sufficient (as opposed to projecting).
506 gfx::Rect layer_rect =
507 MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect());
508 // Skip the quad culler and just append the quads directly to avoid
509 // occlusion checks.
510 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
511 quad->SetNew(shared_quad_state, layer_rect, screen_background_color);
512 quad_culler.Append(quad.PassAs<DrawQuad>(), &append_quads_data);
516 bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
517 DCHECK(frame->render_passes.empty());
519 if (!CanDraw() || !active_tree_->root_layer())
520 return false;
522 TrackDamageForAllSurfaces(active_tree_->root_layer(),
523 *frame->render_surface_layer_list);
525 // If the root render surface has no visible damage, then don't generate a
526 // frame at all.
527 RenderSurfaceImpl* root_surface =
528 active_tree_->root_layer()->render_surface();
529 bool root_surface_has_no_visible_damage =
530 !root_surface->damage_tracker()->current_damage_rect().Intersects(
531 root_surface->content_rect());
532 bool root_surface_has_contributing_layers =
533 !root_surface->layer_list().empty();
534 if (root_surface_has_contributing_layers &&
535 root_surface_has_no_visible_damage) {
536 TRACE_EVENT0("cc",
537 "LayerTreeHostImpl::CalculateRenderPasses::EmptyDamageRect");
538 frame->has_no_damage = true;
539 return true;
542 TRACE_EVENT1("cc",
543 "LayerTreeHostImpl::CalculateRenderPasses",
544 "render_surface_layer_list.size()",
545 static_cast<uint64>(frame->render_surface_layer_list->size()));
547 // Create the render passes in dependency order.
548 for (int surface_index = frame->render_surface_layer_list->size() - 1;
549 surface_index >= 0;
550 --surface_index) {
551 LayerImpl* render_surface_layer =
552 (*frame->render_surface_layer_list)[surface_index];
553 render_surface_layer->render_surface()->AppendRenderPasses(frame);
556 bool record_metrics_for_frame =
557 settings_.show_overdraw_in_tracing &&
558 base::debug::TraceLog::GetInstance() &&
559 base::debug::TraceLog::GetInstance()->IsEnabled();
560 OcclusionTrackerImpl occlusion_tracker(
561 active_tree_->root_layer()->render_surface()->content_rect(),
562 record_metrics_for_frame);
563 occlusion_tracker.set_minimum_tracking_size(
564 settings_.minimum_occlusion_tracking_size);
566 if (debug_state_.show_occluding_rects) {
567 occlusion_tracker.set_occluding_screen_space_rects_container(
568 &frame->occluding_screen_space_rects);
570 if (debug_state_.show_non_occluding_rects) {
571 occlusion_tracker.set_non_occluding_screen_space_rects_container(
572 &frame->non_occluding_screen_space_rects);
575 // Add quads to the Render passes in FrontToBack order to allow for testing
576 // occlusion and performing culling during the tree walk.
577 typedef LayerIterator<LayerImpl,
578 LayerImplList,
579 RenderSurfaceImpl,
580 LayerIteratorActions::FrontToBack> LayerIteratorType;
582 // Typically when we are missing a texture and use a checkerboard quad, we
583 // still draw the frame. However when the layer being checkerboarded is moving
584 // due to an impl-animation, we drop the frame to avoid flashing due to the
585 // texture suddenly appearing in the future.
586 bool draw_frame = true;
587 // When we have a copy request for a layer, we need to draw no matter
588 // what, as the layer may disappear after this frame.
589 bool have_copy_request = false;
591 int layers_drawn = 0;
593 LayerIteratorType end =
594 LayerIteratorType::End(frame->render_surface_layer_list);
595 for (LayerIteratorType it =
596 LayerIteratorType::Begin(frame->render_surface_layer_list);
597 it != end;
598 ++it) {
599 RenderPass::Id target_render_pass_id =
600 it.target_render_surface_layer()->render_surface()->RenderPassId();
601 RenderPass* target_render_pass =
602 frame->render_passes_by_id[target_render_pass_id];
604 bool prevent_occlusion =
605 it.target_render_surface_layer()->HasRequestCopyCallback();
606 occlusion_tracker.EnterLayer(it, prevent_occlusion);
608 AppendQuadsData append_quads_data(target_render_pass->id);
610 if (it.represents_target_render_surface()) {
611 if (it->HasRequestCopyCallback()) {
612 have_copy_request = true;
613 it->TakeRequestCopyCallbacks(&target_render_pass->copy_callbacks);
615 } else if (it.represents_contributing_render_surface()) {
616 RenderPass::Id contributing_render_pass_id =
617 it->render_surface()->RenderPassId();
618 RenderPass* contributing_render_pass =
619 frame->render_passes_by_id[contributing_render_pass_id];
620 AppendQuadsForRenderSurfaceLayer(target_render_pass,
621 *it,
622 contributing_render_pass,
623 occlusion_tracker,
624 &append_quads_data);
625 } else if (it.represents_itself() &&
626 !it->visible_content_rect().IsEmpty()) {
627 bool has_occlusion_from_outside_target_surface;
628 bool impl_draw_transform_is_unknown = false;
629 if (occlusion_tracker.Occluded(
630 it->render_target(),
631 it->visible_content_rect(),
632 it->draw_transform(),
633 impl_draw_transform_is_unknown,
634 it->is_clipped(),
635 it->clip_rect(),
636 &has_occlusion_from_outside_target_surface)) {
637 append_quads_data.had_occlusion_from_outside_target_surface |=
638 has_occlusion_from_outside_target_surface;
639 } else {
640 DCHECK_EQ(active_tree_, it->layer_tree_impl());
641 it->WillDraw(resource_provider_.get());
642 frame->will_draw_layers.push_back(*it);
644 if (it->HasContributingDelegatedRenderPasses()) {
645 RenderPass::Id contributing_render_pass_id =
646 it->FirstContributingRenderPassId();
647 while (frame->render_passes_by_id.find(contributing_render_pass_id) !=
648 frame->render_passes_by_id.end()) {
649 RenderPass* render_pass =
650 frame->render_passes_by_id[contributing_render_pass_id];
652 AppendQuadsData append_quads_data(render_pass->id);
653 AppendQuadsForLayer(render_pass,
654 *it,
655 occlusion_tracker,
656 &append_quads_data);
658 contributing_render_pass_id =
659 it->NextContributingRenderPassId(contributing_render_pass_id);
663 AppendQuadsForLayer(target_render_pass,
664 *it,
665 occlusion_tracker,
666 &append_quads_data);
669 ++layers_drawn;
672 if (append_quads_data.had_occlusion_from_outside_target_surface)
673 target_render_pass->has_occlusion_from_outside_target_surface = true;
675 if (append_quads_data.num_missing_tiles) {
676 rendering_stats_instrumentation_->AddMissingTiles(
677 append_quads_data.num_missing_tiles);
678 bool layer_has_animating_transform =
679 it->screen_space_transform_is_animating() ||
680 it->draw_transform_is_animating();
681 if (layer_has_animating_transform)
682 draw_frame = false;
685 if (append_quads_data.had_incomplete_tile)
686 frame->contains_incomplete_tile = true;
688 occlusion_tracker.LeaveLayer(it);
691 if (have_copy_request)
692 draw_frame = true;
694 rendering_stats_instrumentation_->AddLayersDrawn(layers_drawn);
696 #ifndef NDEBUG
697 for (size_t i = 0; i < frame->render_passes.size(); ++i) {
698 for (size_t j = 0; j < frame->render_passes[i]->quad_list.size(); ++j)
699 DCHECK(frame->render_passes[i]->quad_list[j]->shared_quad_state);
700 DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id)
701 != frame->render_passes_by_id.end());
703 #endif
704 DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin());
706 if (!active_tree_->has_transparent_background()) {
707 frame->render_passes.back()->has_transparent_background = false;
708 AppendQuadsToFillScreen(frame->render_passes.back(),
709 active_tree_->root_layer(),
710 active_tree_->background_color(),
711 occlusion_tracker);
714 if (draw_frame)
715 occlusion_tracker.overdraw_metrics()->RecordMetrics(this);
716 else
717 DCHECK(!have_copy_request);
719 RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame);
720 renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes);
721 RemoveRenderPasses(CullRenderPassesWithCachedTextures(renderer_.get()),
722 frame);
724 // If we're making a frame to draw, it better have at least one render pass.
725 DCHECK(!frame->render_passes.empty());
726 return draw_frame;
729 void LayerTreeHostImpl::UpdateBackgroundAnimateTicking(
730 bool should_background_tick) {
731 bool enabled = should_background_tick &&
732 !animation_registrar_->active_animation_controllers().empty();
734 // Lazily create the time_source adapter so that we can vary the interval for
735 // testing.
736 if (!time_source_client_adapter_) {
737 time_source_client_adapter_ = LayerTreeHostImplTimeSourceAdapter::Create(
738 this,
739 DelayBasedTimeSource::Create(LowFrequencyAnimationInterval(),
740 proxy_->CurrentThread()));
743 time_source_client_adapter_->SetActive(enabled);
746 void LayerTreeHostImpl::SetViewportDamage(gfx::Rect damage_rect) {
747 viewport_damage_rect_.Union(damage_rect);
750 static inline RenderPass* FindRenderPassById(
751 RenderPass::Id render_pass_id,
752 const LayerTreeHostImpl::FrameData& frame) {
753 RenderPassIdHashMap::const_iterator it =
754 frame.render_passes_by_id.find(render_pass_id);
755 return it != frame.render_passes_by_id.end() ? it->second : NULL;
758 static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id,
759 LayerTreeHostImpl::FrameData* frame) {
760 RenderPass* remove_render_pass =
761 FindRenderPassById(remove_render_pass_id, *frame);
762 // The pass was already removed by another quad - probably the original, and
763 // we are the replica.
764 if (!remove_render_pass)
765 return;
766 RenderPassList& render_passes = frame->render_passes;
767 RenderPassList::iterator to_remove = std::find(render_passes.begin(),
768 render_passes.end(),
769 remove_render_pass);
771 DCHECK(to_remove != render_passes.end());
773 scoped_ptr<RenderPass> removed_pass = render_passes.take(to_remove);
774 frame->render_passes.erase(to_remove);
775 frame->render_passes_by_id.erase(remove_render_pass_id);
777 // Now follow up for all RenderPass quads and remove their RenderPasses
778 // recursively.
779 const QuadList& quad_list = removed_pass->quad_list;
780 QuadList::ConstBackToFrontIterator quad_list_iterator =
781 quad_list.BackToFrontBegin();
782 for (; quad_list_iterator != quad_list.BackToFrontEnd();
783 ++quad_list_iterator) {
784 DrawQuad* current_quad = (*quad_list_iterator);
785 if (current_quad->material != DrawQuad::RENDER_PASS)
786 continue;
788 RenderPass::Id next_remove_render_pass_id =
789 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id;
790 RemoveRenderPassesRecursive(next_remove_render_pass_id, frame);
794 bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::
795 ShouldRemoveRenderPass(const RenderPassDrawQuad& quad,
796 const FrameData& frame) const {
797 bool quad_has_damage = !quad.contents_changed_since_last_frame.IsEmpty();
798 bool quad_has_cached_resource =
799 renderer_->HaveCachedResourcesForRenderPassId(quad.render_pass_id);
800 if (quad_has_damage) {
801 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
802 return false;
803 } else if (!quad_has_cached_resource) {
804 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
805 return false;
807 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
808 return true;
811 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass(
812 const RenderPassDrawQuad& quad, const FrameData& frame) const {
813 const RenderPass* render_pass =
814 FindRenderPassById(quad.render_pass_id, frame);
815 if (!render_pass)
816 return false;
818 // If any quad or RenderPass draws into this RenderPass, then keep it.
819 const QuadList& quad_list = render_pass->quad_list;
820 for (QuadList::ConstBackToFrontIterator quad_list_iterator =
821 quad_list.BackToFrontBegin();
822 quad_list_iterator != quad_list.BackToFrontEnd();
823 ++quad_list_iterator) {
824 DrawQuad* current_quad = *quad_list_iterator;
826 if (current_quad->material != DrawQuad::RENDER_PASS)
827 return false;
829 const RenderPass* contributing_pass = FindRenderPassById(
830 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id, frame);
831 if (contributing_pass)
832 return false;
834 return true;
837 // Defined for linking tests.
838 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
839 LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(
840 CullRenderPassesWithCachedTextures culler, FrameData* frame);
841 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses<
842 LayerTreeHostImpl::CullRenderPassesWithNoQuads>(
843 CullRenderPassesWithNoQuads culler, FrameData*);
845 // static
846 template <typename RenderPassCuller>
847 void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler,
848 FrameData* frame) {
849 for (size_t it = culler.RenderPassListBegin(frame->render_passes);
850 it != culler.RenderPassListEnd(frame->render_passes);
851 it = culler.RenderPassListNext(it)) {
852 const RenderPass* current_pass = frame->render_passes[it];
853 const QuadList& quad_list = current_pass->quad_list;
854 QuadList::ConstBackToFrontIterator quad_list_iterator =
855 quad_list.BackToFrontBegin();
857 for (; quad_list_iterator != quad_list.BackToFrontEnd();
858 ++quad_list_iterator) {
859 DrawQuad* current_quad = *quad_list_iterator;
861 if (current_quad->material != DrawQuad::RENDER_PASS)
862 continue;
864 const RenderPassDrawQuad* render_pass_quad =
865 RenderPassDrawQuad::MaterialCast(current_quad);
866 if (!culler.ShouldRemoveRenderPass(*render_pass_quad, *frame))
867 continue;
869 // We are changing the vector in the middle of iteration. Because we
870 // delete render passes that draw into the current pass, we are
871 // guaranteed that any data from the iterator to the end will not
872 // change. So, capture the iterator position from the end of the
873 // list, and restore it after the change.
874 size_t position_from_end = frame->render_passes.size() - it;
875 RemoveRenderPassesRecursive(render_pass_quad->render_pass_id, frame);
876 it = frame->render_passes.size() - position_from_end;
877 DCHECK_GE(frame->render_passes.size(), position_from_end);
882 bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame,
883 gfx::Rect device_viewport_damage_rect) {
884 TRACE_EVENT0("cc", "LayerTreeHostImpl::PrepareToDraw");
886 active_tree_->UpdateDrawProperties(
887 LayerTreeImpl::UPDATE_ACTIVE_TREE_FOR_DRAW);
889 frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList();
890 frame->render_passes.clear();
891 frame->render_passes_by_id.clear();
892 frame->will_draw_layers.clear();
893 frame->contains_incomplete_tile = false;
894 frame->has_no_damage = false;
896 if (active_tree_->root_layer()) {
897 device_viewport_damage_rect.Union(viewport_damage_rect_);
898 viewport_damage_rect_ = gfx::Rect();
900 active_tree_->root_layer()->render_surface()->damage_tracker()->
901 AddDamageNextUpdate(device_viewport_damage_rect);
904 if (!CalculateRenderPasses(frame))
905 return false;
907 frame->latency_info = active_tree_->GetLatencyInfo();
909 // If we return true, then we expect DrawLayers() to be called before this
910 // function is called again.
911 return true;
914 void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
915 const ManagedMemoryPolicy& policy) {
916 bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread(
917 visible_ ? policy.bytes_limit_when_visible
918 : policy.bytes_limit_when_not_visible,
919 ManagedMemoryPolicy::PriorityCutoffToValue(
920 visible_ ? policy.priority_cutoff_when_visible
921 : policy.priority_cutoff_when_not_visible));
922 if (evicted_resources) {
923 active_tree_->SetContentsTexturesPurged();
924 if (pending_tree_)
925 pending_tree_->SetContentsTexturesPurged();
926 client_->SetNeedsCommitOnImplThread();
927 client_->OnCanDrawStateChanged(CanDraw());
928 client_->RenewTreePriority();
930 client_->SendManagedMemoryStats();
932 if (tile_manager_) {
933 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
934 new_state.memory_limit_in_bytes = visible_ ?
935 policy.bytes_limit_when_visible :
936 policy.bytes_limit_when_not_visible;
937 // TODO(reveman): We should avoid keeping around unused resources if
938 // possible. crbug.com/224475
939 new_state.unused_memory_limit_in_bytes = static_cast<size_t>(
940 (static_cast<int64>(new_state.memory_limit_in_bytes) *
941 settings_.max_unused_resource_memory_percentage) / 100);
942 new_state.memory_limit_policy =
943 ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy(
944 visible_ ?
945 policy.priority_cutoff_when_visible :
946 policy.priority_cutoff_when_not_visible);
947 tile_manager_->SetGlobalState(new_state);
951 bool LayerTreeHostImpl::HasImplThread() const {
952 return proxy_->HasImplThread();
955 void LayerTreeHostImpl::ScheduleManageTiles() {
956 if (client_)
957 client_->SetNeedsManageTilesOnImplThread();
960 void LayerTreeHostImpl::DidInitializeVisibleTile() {
961 // TODO(reveman): Determine tiles that changed and only damage
962 // what's necessary.
963 SetFullRootLayerDamage();
964 if (client_)
965 client_->DidInitializeVisibleTileOnImplThread();
968 bool LayerTreeHostImpl::ShouldClearRootRenderPass() const {
969 return settings_.should_clear_root_render_pass;
972 void LayerTreeHostImpl::SetManagedMemoryPolicy(
973 const ManagedMemoryPolicy& policy) {
974 if (managed_memory_policy_ == policy)
975 return;
977 // If there is already enough memory to draw everything imaginable and the
978 // new memory limit does not change this, then do not re-commit. Don't bother
979 // skipping commits if this is not visible (commits don't happen when not
980 // visible, there will almost always be a commit when this becomes visible).
981 bool needs_commit = true;
982 if (visible() &&
983 policy.bytes_limit_when_visible >=
984 max_memory_needed_bytes_ &&
985 managed_memory_policy_.bytes_limit_when_visible >=
986 max_memory_needed_bytes_ &&
987 policy.priority_cutoff_when_visible ==
988 managed_memory_policy_.priority_cutoff_when_visible) {
989 needs_commit = false;
992 managed_memory_policy_ = policy;
993 if (!proxy_->HasImplThread()) {
994 // In single-thread mode, this can be called on the main thread by
995 // GLRenderer::OnMemoryAllocationChanged.
996 DebugScopedSetImplThread impl_thread(proxy_);
997 EnforceManagedMemoryPolicy(managed_memory_policy_);
998 } else {
999 DCHECK(proxy_->IsImplThread());
1000 EnforceManagedMemoryPolicy(managed_memory_policy_);
1003 if (needs_commit)
1004 client_->SetNeedsCommitOnImplThread();
1007 void LayerTreeHostImpl::SetNeedsRedrawRect(gfx::Rect damage_rect) {
1008 client_->SetNeedsRedrawRectOnImplThread(damage_rect);
1011 void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase,
1012 base::TimeDelta interval) {
1013 client_->OnVSyncParametersChanged(timebase, interval);
1016 void LayerTreeHostImpl::DidVSync(base::TimeTicks frame_time) {
1017 client_->DidVSync(frame_time);
1020 void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(
1021 const CompositorFrameAck& ack) {
1022 if (!renderer_)
1023 return;
1025 // TODO(piman): We may need to do some validation on this ack before
1026 // processing it.
1027 renderer_->ReceiveCompositorFrameAck(ack);
1029 // When using compositor frame data, the ack doubles as a swap complete ack.
1030 OnSwapBuffersComplete();
1033 void LayerTreeHostImpl::OnCanDrawStateChangedForTree() {
1034 client_->OnCanDrawStateChanged(CanDraw());
1037 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
1038 CompositorFrameMetadata metadata;
1039 metadata.device_scale_factor = device_scale_factor_;
1040 metadata.page_scale_factor = active_tree_->total_page_scale_factor();
1041 metadata.viewport_size = active_tree_->ScrollableViewportSize();
1042 metadata.root_layer_size = active_tree_->ScrollableSize();
1043 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor();
1044 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor();
1045 if (top_controls_manager_) {
1046 metadata.location_bar_offset =
1047 gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset());
1048 metadata.location_bar_content_translation =
1049 gfx::Vector2dF(0.f, top_controls_manager_->content_top_offset());
1050 metadata.overdraw_bottom_height = overdraw_bottom_height_;
1053 if (!RootScrollLayer())
1054 return metadata;
1056 metadata.root_scroll_offset = RootScrollLayer()->TotalScrollOffset();
1057 metadata.latency_info = active_tree_->GetLatencyInfo();
1059 return metadata;
1062 bool LayerTreeHostImpl::AllowPartialSwap() const {
1063 // We don't track damage on the HUD layer (it interacts with damage tracking
1064 // visualizations), so disable partial swaps to make the HUD layer display
1065 // properly.
1066 return !debug_state_.ShowHudRects();
1069 void LayerTreeHostImpl::DrawLayers(FrameData* frame,
1070 base::TimeTicks frame_begin_time) {
1071 TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers");
1072 DCHECK(CanDraw());
1074 if (frame->has_no_damage)
1075 return;
1077 DCHECK(!frame->render_passes.empty());
1079 fps_counter_->SaveTimeStamp(frame_begin_time);
1081 rendering_stats_instrumentation_->SetScreenFrameCount(
1082 fps_counter_->current_frame_number());
1083 rendering_stats_instrumentation_->SetDroppedFrameCount(
1084 fps_counter_->dropped_frame_count());
1086 if (tile_manager_) {
1087 memory_history_->SaveEntry(
1088 tile_manager_->memory_stats_from_last_assign());
1091 if (debug_state_.ShowHudRects()) {
1092 debug_rect_history_->SaveDebugRectsForCurrentFrame(
1093 active_tree_->root_layer(),
1094 *frame->render_surface_layer_list,
1095 frame->occluding_screen_space_rects,
1096 frame->non_occluding_screen_space_rects,
1097 debug_state_);
1100 if (!settings_.impl_side_painting && debug_state_.continuous_painting) {
1101 const RenderingStats& stats =
1102 rendering_stats_instrumentation_->GetRenderingStats();
1103 paint_time_counter_->SavePaintTime(stats.total_paint_time);
1106 if (debug_state_.trace_all_rendered_frames) {
1107 TRACE_EVENT_INSTANT1("cc.debug", "Frame", TRACE_EVENT_SCOPE_THREAD,
1108 "frame", ValueToString(FrameStateAsValue()));
1111 // Because the contents of the HUD depend on everything else in the frame, the
1112 // contents of its texture are updated as the last thing before the frame is
1113 // drawn.
1114 if (active_tree_->hud_layer())
1115 active_tree_->hud_layer()->UpdateHudTexture(resource_provider_.get());
1117 renderer_->DrawFrame(&frame->render_passes);
1118 // The render passes should be consumed by the renderer.
1119 DCHECK(frame->render_passes.empty());
1120 frame->render_passes_by_id.clear();
1122 // The next frame should start by assuming nothing has changed, and changes
1123 // are noted as they occur.
1124 for (size_t i = 0; i < frame->render_surface_layer_list->size(); i++) {
1125 (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()->
1126 DidDrawDamagedArea();
1128 active_tree_->root_layer()->ResetAllChangeTrackingForSubtree();
1131 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) {
1132 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i)
1133 frame.will_draw_layers[i]->DidDraw(resource_provider_.get());
1135 // Once all layers have been drawn, pending texture uploads should no
1136 // longer block future uploads.
1137 resource_provider_->MarkPendingUploadsAsNonBlocking();
1140 void LayerTreeHostImpl::FinishAllRendering() {
1141 if (renderer_)
1142 renderer_->Finish();
1145 bool LayerTreeHostImpl::IsContextLost() {
1146 DCHECK(proxy_->IsImplThread());
1147 return renderer_ && renderer_->IsContextLost();
1150 const RendererCapabilities& LayerTreeHostImpl::GetRendererCapabilities() const {
1151 return renderer_->Capabilities();
1154 bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
1155 if (frame.has_no_damage)
1156 return false;
1157 bool result = renderer_->SwapBuffers(frame.latency_info);
1158 if (result)
1159 active_tree_->ClearLatencyInfo();
1160 return result;
1163 void LayerTreeHostImpl::EnableVSyncNotification(bool enable) {
1164 if (output_surface_)
1165 output_surface_->EnableVSyncNotification(enable);
1168 gfx::Size LayerTreeHostImpl::DeviceViewportSize() const {
1169 return device_viewport_size();
1172 gfx::SizeF LayerTreeHostImpl::VisibleViewportSize() const {
1173 gfx::SizeF dip_size =
1174 gfx::ScaleSize(DeviceViewportSize(), 1.f / device_scale_factor());
1176 // The clip layer should be used if non-overlay scrollbars may exist since
1177 // it adjusts for them.
1178 LayerImpl* clip_layer = active_tree_->RootClipLayer();
1179 if (!Settings().solid_color_scrollbars && clip_layer &&
1180 clip_layer->masks_to_bounds())
1181 dip_size = clip_layer->bounds();
1183 float top_offset =
1184 top_controls_manager_ ? top_controls_manager_->content_top_offset() : 0.f;
1185 return gfx::SizeF(dip_size.width(),
1186 dip_size.height() - top_offset - overdraw_bottom_height_);
1189 const LayerTreeSettings& LayerTreeHostImpl::Settings() const {
1190 return settings();
1193 void LayerTreeHostImpl::DidLoseOutputSurface() {
1194 // TODO(jamesr): The renderer_ check is needed to make some of the
1195 // LayerTreeHostContextTest tests pass, but shouldn't be necessary (or
1196 // important) in production. We should adjust the test to not need this.
1197 if (renderer_)
1198 client_->DidLoseOutputSurfaceOnImplThread();
1201 void LayerTreeHostImpl::OnSwapBuffersComplete() {
1202 client_->OnSwapBuffersCompleteOnImplThread();
1205 void LayerTreeHostImpl::Readback(void* pixels,
1206 gfx::Rect rect_in_device_viewport) {
1207 DCHECK(renderer_);
1208 renderer_->GetFramebufferPixels(pixels, rect_in_device_viewport);
1211 bool LayerTreeHostImpl::HaveRootScrollLayer() const {
1212 return !!RootScrollLayer();
1215 LayerImpl* LayerTreeHostImpl::RootLayer() const {
1216 return active_tree_->root_layer();
1219 LayerImpl* LayerTreeHostImpl::RootScrollLayer() const {
1220 return active_tree_->RootScrollLayer();
1223 LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const {
1224 return active_tree_->CurrentlyScrollingLayer();
1227 // Content layers can be either directly scrollable or contained in an outer
1228 // scrolling layer which applies the scroll transform. Given a content layer,
1229 // this function returns the associated scroll layer if any.
1230 static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) {
1231 if (!layer_impl)
1232 return 0;
1234 if (layer_impl->scrollable())
1235 return layer_impl;
1237 if (layer_impl->DrawsContent() &&
1238 layer_impl->parent() &&
1239 layer_impl->parent()->scrollable())
1240 return layer_impl->parent();
1242 return 0;
1245 void LayerTreeHostImpl::CreatePendingTree() {
1246 CHECK(!pending_tree_);
1247 if (recycle_tree_)
1248 recycle_tree_.swap(pending_tree_);
1249 else
1250 pending_tree_ = LayerTreeImpl::create(this);
1251 client_->OnCanDrawStateChanged(CanDraw());
1252 client_->OnHasPendingTreeStateChanged(pending_tree_);
1253 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", pending_tree_.get());
1254 TRACE_EVENT_ASYNC_STEP0("cc",
1255 "PendingTree", pending_tree_.get(), "waiting");
1258 void LayerTreeHostImpl::CheckForCompletedTileUploads() {
1259 DCHECK(!client_->IsInsideDraw()) <<
1260 "Checking for completed uploads within a draw may trigger "
1261 "spurious redraws.";
1262 if (tile_manager_)
1263 tile_manager_->CheckForCompletedTileUploads();
1266 bool LayerTreeHostImpl::ActivatePendingTreeIfNeeded() {
1267 if (!pending_tree_)
1268 return false;
1270 CHECK(tile_manager_);
1272 pending_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE);
1274 TRACE_EVENT_ASYNC_STEP1("cc",
1275 "PendingTree", pending_tree_.get(), "activate",
1276 "state", ValueToString(ActivationStateAsValue()));
1278 // Activate once all visible resources in pending tree are ready.
1279 if (!pending_tree_->AreVisibleResourcesReady())
1280 return false;
1282 ActivatePendingTree();
1283 return true;
1286 void LayerTreeHostImpl::ActivatePendingTree() {
1287 CHECK(pending_tree_);
1288 TRACE_EVENT_ASYNC_END0("cc", "PendingTree", pending_tree_.get());
1290 active_tree_->PushPersistedState(pending_tree_.get());
1291 if (pending_tree_->needs_full_tree_sync()) {
1292 active_tree_->SetRootLayer(
1293 TreeSynchronizer::SynchronizeTrees(pending_tree_->root_layer(),
1294 active_tree_->DetachLayerTree(),
1295 active_tree_.get()));
1297 TreeSynchronizer::PushProperties(pending_tree_->root_layer(),
1298 active_tree_->root_layer());
1299 DCHECK(!recycle_tree_);
1301 pending_tree_->PushPropertiesTo(active_tree_.get());
1303 // Now that we've synced everything from the pending tree to the active
1304 // tree, rename the pending tree the recycle tree so we can reuse it on the
1305 // next sync.
1306 pending_tree_.swap(recycle_tree_);
1307 recycle_tree_->ClearRenderSurfaces();
1309 active_tree_->DidBecomeActive();
1311 // Reduce wasted memory now that unlinked resources are guaranteed not
1312 // to be used.
1313 client_->ReduceWastedContentsTextureMemoryOnImplThread();
1315 client_->OnCanDrawStateChanged(CanDraw());
1316 client_->OnHasPendingTreeStateChanged(pending_tree_);
1317 client_->SetNeedsRedrawOnImplThread();
1318 client_->RenewTreePriority();
1320 if (debug_state_.continuous_painting) {
1321 const RenderingStats& stats =
1322 rendering_stats_instrumentation_->GetRenderingStats();
1323 paint_time_counter_->SavePaintTime(
1324 stats.total_paint_time + stats.total_record_time +
1325 stats.total_rasterize_time_for_now_bins_on_pending_tree);
1329 void LayerTreeHostImpl::SetVisible(bool visible) {
1330 DCHECK(proxy_->IsImplThread());
1332 if (visible_ == visible)
1333 return;
1334 visible_ = visible;
1335 DidVisibilityChange(this, visible_);
1336 EnforceManagedMemoryPolicy(managed_memory_policy_);
1338 if (!renderer_)
1339 return;
1341 renderer_->SetVisible(visible);
1344 bool LayerTreeHostImpl::InitializeRenderer(
1345 scoped_ptr<OutputSurface> output_surface) {
1346 // Since we will create a new resource provider, we cannot continue to use
1347 // the old resources (i.e. render_surfaces and texture IDs). Clear them
1348 // before we destroy the old resource provider.
1349 if (active_tree_->root_layer())
1350 ClearRenderSurfaces();
1351 if (active_tree_->root_layer())
1352 SendDidLoseOutputSurfaceRecursive(active_tree_->root_layer());
1353 if (pending_tree_ && pending_tree_->root_layer())
1354 SendDidLoseOutputSurfaceRecursive(pending_tree_->root_layer());
1355 if (recycle_tree_ && recycle_tree_->root_layer())
1356 SendDidLoseOutputSurfaceRecursive(recycle_tree_->root_layer());
1357 if (resource_provider_)
1358 resource_provider_->DidLoseOutputSurface();
1360 // Note: order is important here.
1361 renderer_.reset();
1362 tile_manager_.reset();
1363 resource_provider_.reset();
1364 output_surface_.reset();
1366 if (!output_surface->BindToClient(this))
1367 return false;
1369 scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
1370 output_surface.get(), settings_.highp_threshold_min);
1371 if (!resource_provider)
1372 return false;
1374 if (settings_.impl_side_painting) {
1375 tile_manager_.reset(new TileManager(this,
1376 resource_provider.get(),
1377 settings_.num_raster_threads,
1378 settings_.use_cheapness_estimator,
1379 settings_.use_color_estimator,
1380 settings_.prediction_benchmarking,
1381 rendering_stats_instrumentation_));
1384 if (output_surface->capabilities().has_parent_compositor) {
1385 renderer_ = DelegatingRenderer::Create(this, output_surface.get(),
1386 resource_provider.get());
1387 } else if (output_surface->context3d()) {
1388 renderer_ = GLRenderer::Create(this,
1389 output_surface.get(),
1390 resource_provider.get(),
1391 settings_.highp_threshold_min);
1392 } else if (output_surface->software_device()) {
1393 renderer_ = SoftwareRenderer::Create(this,
1394 output_surface.get(),
1395 resource_provider.get());
1397 if (!renderer_)
1398 return false;
1400 resource_provider_ = resource_provider.Pass();
1401 output_surface_ = output_surface.Pass();
1403 if (!visible_)
1404 renderer_->SetVisible(visible_);
1406 client_->OnCanDrawStateChanged(CanDraw());
1408 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs
1409 // to be initialized to get max texture size.
1410 active_tree_->set_needs_update_draw_properties();
1411 if (pending_tree_)
1412 pending_tree_->set_needs_update_draw_properties();
1414 return true;
1417 void LayerTreeHostImpl::SetViewportSize(gfx::Size device_viewport_size) {
1418 if (device_viewport_size == device_viewport_size_)
1419 return;
1421 if (pending_tree_ && device_viewport_size_ != device_viewport_size)
1422 active_tree_->SetViewportSizeInvalid();
1424 device_viewport_size_ = device_viewport_size;
1426 UpdateMaxScrollOffset();
1428 if (renderer_)
1429 renderer_->ViewportChanged();
1431 client_->OnCanDrawStateChanged(CanDraw());
1432 SetFullRootLayerDamage();
1435 void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) {
1436 if (overdraw_bottom_height == overdraw_bottom_height_)
1437 return;
1438 overdraw_bottom_height_ = overdraw_bottom_height;
1440 UpdateMaxScrollOffset();
1441 SetFullRootLayerDamage();
1444 void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) {
1445 if (device_scale_factor == device_scale_factor_)
1446 return;
1447 device_scale_factor_ = device_scale_factor;
1449 UpdateMaxScrollOffset();
1450 SetFullRootLayerDamage();
1453 void LayerTreeHostImpl::UpdateMaxScrollOffset() {
1454 active_tree_->UpdateMaxScrollOffset();
1457 void LayerTreeHostImpl::DidChangeTopControlsPosition() {
1458 client_->SetNeedsRedrawOnImplThread();
1459 active_tree_->set_needs_update_draw_properties();
1460 SetFullRootLayerDamage();
1463 bool LayerTreeHostImpl::EnsureRenderSurfaceLayerList() {
1464 active_tree_->UpdateDrawProperties(LayerTreeImpl::UPDATE_ACTIVE_TREE);
1465 return !active_tree_->RenderSurfaceLayerList().empty();
1468 InputHandlerClient::ScrollStatus LayerTreeHostImpl::ScrollBegin(
1469 gfx::Point viewport_point, InputHandlerClient::ScrollInputType type) {
1470 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin");
1472 if (top_controls_manager_)
1473 top_controls_manager_->ScrollBegin();
1475 DCHECK(!CurrentlyScrollingLayer());
1476 ClearCurrentlyScrollingLayer();
1478 if (!EnsureRenderSurfaceLayerList())
1479 return ScrollIgnored;
1481 gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point,
1482 device_scale_factor_);
1484 // First find out which layer was hit from the saved list of visible layers
1485 // in the most recent frame.
1486 LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint(
1487 device_viewport_point, active_tree_->RenderSurfaceLayerList());
1489 // Walk up the hierarchy and look for a scrollable layer.
1490 LayerImpl* potentially_scrolling_layer_impl = 0;
1491 for (; layer_impl; layer_impl = layer_impl->parent()) {
1492 // The content layer can also block attempts to scroll outside the main
1493 // thread.
1494 ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type);
1495 if (status == ScrollOnMainThread) {
1496 rendering_stats_instrumentation_->IncrementMainThreadScrolls();
1497 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1498 active_tree()->DidBeginScroll();
1499 return ScrollOnMainThread;
1502 LayerImpl* scroll_layer_impl = FindScrollLayerForContentLayer(layer_impl);
1503 if (!scroll_layer_impl)
1504 continue;
1506 status = scroll_layer_impl->TryScroll(device_viewport_point, type);
1508 // If any layer wants to divert the scroll event to the main thread, abort.
1509 if (status == ScrollOnMainThread) {
1510 rendering_stats_instrumentation_->IncrementMainThreadScrolls();
1511 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true);
1512 active_tree()->DidBeginScroll();
1513 return ScrollOnMainThread;
1516 if (status == ScrollStarted && !potentially_scrolling_layer_impl)
1517 potentially_scrolling_layer_impl = scroll_layer_impl;
1520 // When hiding top controls is enabled and the controls are hidden or
1521 // overlaying the content, force scrolls to be enabled on the root layer to
1522 // allow bringing the top controls back into view.
1523 if (!potentially_scrolling_layer_impl && top_controls_manager_ &&
1524 top_controls_manager_->content_top_offset() !=
1525 settings_.top_controls_height) {
1526 potentially_scrolling_layer_impl = RootScrollLayer();
1529 if (potentially_scrolling_layer_impl) {
1530 active_tree_->SetCurrentlyScrollingLayer(
1531 potentially_scrolling_layer_impl);
1532 should_bubble_scrolls_ = (type != NonBubblingGesture);
1533 wheel_scrolling_ = (type == Wheel);
1534 rendering_stats_instrumentation_->IncrementImplThreadScrolls();
1535 client_->RenewTreePriority();
1536 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false);
1537 active_tree()->DidBeginScroll();
1538 return ScrollStarted;
1540 return ScrollIgnored;
1543 gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta(
1544 LayerImpl* layer_impl,
1545 float scale_from_viewport_to_screen_space,
1546 gfx::PointF viewport_point,
1547 gfx::Vector2dF viewport_delta) {
1548 // Layers with non-invertible screen space transforms should not have passed
1549 // the scroll hit test in the first place.
1550 DCHECK(layer_impl->screen_space_transform().IsInvertible());
1551 gfx::Transform inverse_screen_space_transform(
1552 gfx::Transform::kSkipInitialization);
1553 bool did_invert = layer_impl->screen_space_transform().GetInverse(
1554 &inverse_screen_space_transform);
1555 // TODO(shawnsingh): With the advent of impl-side crolling for non-root
1556 // layers, we may need to explicitly handle uninvertible transforms here.
1557 DCHECK(did_invert);
1559 gfx::PointF screen_space_point =
1560 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space);
1562 gfx::Vector2dF screen_space_delta = viewport_delta;
1563 screen_space_delta.Scale(scale_from_viewport_to_screen_space);
1565 // First project the scroll start and end points to local layer space to find
1566 // the scroll delta in layer coordinates.
1567 bool start_clipped, end_clipped;
1568 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta;
1569 gfx::PointF local_start_point =
1570 MathUtil::ProjectPoint(inverse_screen_space_transform,
1571 screen_space_point,
1572 &start_clipped);
1573 gfx::PointF local_end_point =
1574 MathUtil::ProjectPoint(inverse_screen_space_transform,
1575 screen_space_end_point,
1576 &end_clipped);
1578 // In general scroll point coordinates should not get clipped.
1579 DCHECK(!start_clipped);
1580 DCHECK(!end_clipped);
1581 if (start_clipped || end_clipped)
1582 return gfx::Vector2dF();
1584 // local_start_point and local_end_point are in content space but we want to
1585 // move them to layer space for scrolling.
1586 float width_scale = 1.f / layer_impl->contents_scale_x();
1587 float height_scale = 1.f / layer_impl->contents_scale_y();
1588 local_start_point.Scale(width_scale, height_scale);
1589 local_end_point.Scale(width_scale, height_scale);
1591 // Apply the scroll delta.
1592 gfx::Vector2dF previous_delta = layer_impl->scroll_delta();
1593 layer_impl->ScrollBy(local_end_point - local_start_point);
1595 // Get the end point in the layer's content space so we can apply its
1596 // ScreenSpaceTransform.
1597 gfx::PointF actual_local_end_point = local_start_point +
1598 layer_impl->scroll_delta() -
1599 previous_delta;
1600 gfx::PointF actual_local_content_end_point =
1601 gfx::ScalePoint(actual_local_end_point,
1602 1.f / width_scale,
1603 1.f / height_scale);
1605 // Calculate the applied scroll delta in viewport space coordinates.
1606 gfx::PointF actual_screen_space_end_point =
1607 MathUtil::MapPoint(layer_impl->screen_space_transform(),
1608 actual_local_content_end_point,
1609 &end_clipped);
1610 DCHECK(!end_clipped);
1611 if (end_clipped)
1612 return gfx::Vector2dF();
1613 gfx::PointF actual_viewport_end_point =
1614 gfx::ScalePoint(actual_screen_space_end_point,
1615 1.f / scale_from_viewport_to_screen_space);
1616 return actual_viewport_end_point - viewport_point;
1619 static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl,
1620 gfx::Vector2dF local_delta) {
1621 gfx::Vector2dF previous_delta(layer_impl->scroll_delta());
1622 layer_impl->ScrollBy(local_delta);
1623 return layer_impl->scroll_delta() - previous_delta;
1626 bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point,
1627 gfx::Vector2dF scroll_delta) {
1628 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
1629 if (!CurrentlyScrollingLayer())
1630 return false;
1632 gfx::Vector2dF pending_delta = scroll_delta;
1633 bool did_scroll = false;
1634 bool consume_by_top_controls = top_controls_manager_ &&
1635 (CurrentlyScrollingLayer() == RootScrollLayer() || scroll_delta.y() < 0);
1637 for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
1638 layer_impl;
1639 layer_impl = layer_impl->parent()) {
1640 if (!layer_impl->scrollable())
1641 continue;
1643 // Only allow bubble scrolling when the scroll is in the direction to make
1644 // the top controls visible.
1645 if (consume_by_top_controls && layer_impl == RootScrollLayer()) {
1646 pending_delta = top_controls_manager_->ScrollBy(pending_delta);
1647 UpdateMaxScrollOffset();
1650 gfx::Vector2dF applied_delta;
1651 // Gesture events need to be transformed from viewport coordinates to local
1652 // layer coordinates so that the scrolling contents exactly follow the
1653 // user's finger. In contrast, wheel events represent a fixed amount of
1654 // scrolling so we can just apply them directly.
1655 if (!wheel_scrolling_) {
1656 float scale_from_viewport_to_screen_space = device_scale_factor_;
1657 applied_delta =
1658 ScrollLayerWithViewportSpaceDelta(layer_impl,
1659 scale_from_viewport_to_screen_space,
1660 viewport_point, pending_delta);
1661 } else {
1662 applied_delta = ScrollLayerWithLocalDelta(layer_impl, pending_delta);
1665 // If the layer wasn't able to move, try the next one in the hierarchy.
1666 float move_threshold_squared = 0.1f * 0.1f;
1667 if (applied_delta.LengthSquared() < move_threshold_squared) {
1668 if (should_bubble_scrolls_ || !did_lock_scrolling_layer_)
1669 continue;
1670 else
1671 break;
1673 did_scroll = true;
1674 did_lock_scrolling_layer_ = true;
1675 if (!should_bubble_scrolls_) {
1676 active_tree_->SetCurrentlyScrollingLayer(layer_impl);
1677 break;
1680 // If the applied delta is within 45 degrees of the input delta, bail out to
1681 // make it easier to scroll just one layer in one direction without
1682 // affecting any of its parents.
1683 float angle_threshold = 45;
1684 if (MathUtil::SmallestAngleBetweenVectors(
1685 applied_delta, pending_delta) < angle_threshold) {
1686 pending_delta = gfx::Vector2d();
1687 break;
1690 // Allow further movement only on an axis perpendicular to the direction in
1691 // which the layer moved.
1692 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
1693 pending_delta = MathUtil::ProjectVector(pending_delta, perpendicular_axis);
1695 if (gfx::ToFlooredVector2d(pending_delta).IsZero())
1696 break;
1699 active_tree()->DidUpdateScroll();
1700 if (did_scroll) {
1701 client_->SetNeedsCommitOnImplThread();
1702 client_->SetNeedsRedrawOnImplThread();
1703 client_->RenewTreePriority();
1705 return did_scroll;
1708 // This implements scrolling by page as described here:
1709 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms645601(v=vs.85).aspx#_win32_The_Mouse_Wheel
1710 // for events with WHEEL_PAGESCROLL set.
1711 bool LayerTreeHostImpl::ScrollVerticallyByPage(
1712 gfx::Point viewport_point,
1713 WebKit::WebScrollbar::ScrollDirection direction) {
1714 DCHECK(wheel_scrolling_);
1716 for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
1717 layer_impl;
1718 layer_impl = layer_impl->parent()) {
1719 if (!layer_impl->scrollable())
1720 continue;
1722 if (!layer_impl->vertical_scrollbar_layer())
1723 continue;
1725 float height = layer_impl->vertical_scrollbar_layer()->bounds().height();
1727 // These magical values match WebKit and are designed to scroll nearly the
1728 // entire visible content height but leave a bit of overlap.
1729 float page = std::max(height * 0.875f, 1.f);
1730 if (direction == WebKit::WebScrollbar::ScrollBackward)
1731 page = -page;
1733 gfx::Vector2dF delta = gfx::Vector2dF(0.f, page);
1735 gfx::Vector2dF applied_delta = ScrollLayerWithLocalDelta(layer_impl, delta);
1737 if (!applied_delta.IsZero()) {
1738 active_tree()->DidUpdateScroll();
1739 client_->SetNeedsCommitOnImplThread();
1740 client_->SetNeedsRedrawOnImplThread();
1741 client_->RenewTreePriority();
1742 return true;
1745 active_tree_->SetCurrentlyScrollingLayer(layer_impl);
1748 return false;
1751 void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() {
1752 active_tree_->ClearCurrentlyScrollingLayer();
1753 did_lock_scrolling_layer_ = false;
1756 void LayerTreeHostImpl::ScrollEnd() {
1757 if (top_controls_manager_)
1758 top_controls_manager_->ScrollEnd();
1759 ClearCurrentlyScrollingLayer();
1760 active_tree()->DidEndScroll();
1761 StartScrollbarAnimation(CurrentFrameTimeTicks());
1764 InputHandlerClient::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() {
1765 if (active_tree_->CurrentlyScrollingLayer())
1766 return ScrollStarted;
1768 return ScrollIgnored;
1771 void LayerTreeHostImpl::PinchGestureBegin() {
1772 pinch_gesture_active_ = true;
1773 previous_pinch_anchor_ = gfx::Point();
1774 client_->RenewTreePriority();
1777 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
1778 gfx::Point anchor) {
1779 TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate");
1781 if (!RootScrollLayer())
1782 return;
1784 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1785 // position over the course of the magnify.
1786 float page_scale_delta = active_tree_->page_scale_delta();
1787 gfx::PointF previous_scale_anchor =
1788 gfx::ScalePoint(anchor, 1.f / page_scale_delta);
1789 active_tree_->SetPageScaleDelta(page_scale_delta * magnify_delta);
1790 page_scale_delta = active_tree_->page_scale_delta();
1791 gfx::PointF new_scale_anchor =
1792 gfx::ScalePoint(anchor, 1.f / page_scale_delta);
1793 gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor;
1795 previous_pinch_anchor_ = anchor;
1797 move.Scale(1 / active_tree_->page_scale_factor());
1799 RootScrollLayer()->ScrollBy(move);
1801 client_->SetNeedsCommitOnImplThread();
1802 client_->SetNeedsRedrawOnImplThread();
1803 client_->RenewTreePriority();
1806 void LayerTreeHostImpl::PinchGestureEnd() {
1807 pinch_gesture_active_ = false;
1808 client_->SetNeedsCommitOnImplThread();
1811 static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info,
1812 LayerImpl* layer_impl) {
1813 if (!layer_impl)
1814 return;
1816 gfx::Vector2d scroll_delta =
1817 gfx::ToFlooredVector2d(layer_impl->scroll_delta());
1818 if (!scroll_delta.IsZero()) {
1819 LayerTreeHostCommon::ScrollUpdateInfo scroll;
1820 scroll.layer_id = layer_impl->id();
1821 scroll.scroll_delta = scroll_delta;
1822 scroll_info->scrolls.push_back(scroll);
1823 layer_impl->SetSentScrollDelta(scroll_delta);
1826 for (size_t i = 0; i < layer_impl->children().size(); ++i)
1827 CollectScrollDeltas(scroll_info, layer_impl->children()[i]);
1830 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() {
1831 scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet());
1833 CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer());
1834 scroll_info->page_scale_delta = active_tree_->page_scale_delta();
1835 active_tree_->set_sent_page_scale_delta(scroll_info->page_scale_delta);
1837 return scroll_info.Pass();
1840 void LayerTreeHostImpl::SetFullRootLayerDamage() {
1841 SetViewportDamage(gfx::Rect(device_viewport_size_));
1844 void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) {
1845 if (!page_scale_animation_ || !RootScrollLayer())
1846 return;
1848 double monotonic_time = (time - base::TimeTicks()).InSecondsF();
1849 gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() +
1850 RootScrollLayer()->scroll_delta();
1852 active_tree_->SetPageScaleDelta(
1853 page_scale_animation_->PageScaleFactorAtTime(monotonic_time) /
1854 active_tree_->page_scale_factor());
1855 gfx::Vector2dF next_scroll =
1856 page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
1858 RootScrollLayer()->ScrollBy(next_scroll - scroll_total);
1859 client_->SetNeedsRedrawOnImplThread();
1861 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
1862 page_scale_animation_.reset();
1863 client_->SetNeedsCommitOnImplThread();
1864 client_->RenewTreePriority();
1868 void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) {
1869 if (!top_controls_manager_ || !RootScrollLayer())
1870 return;
1871 gfx::Vector2dF scroll = top_controls_manager_->Animate(time);
1872 UpdateMaxScrollOffset();
1873 RootScrollLayer()->ScrollBy(gfx::ScaleVector2d(
1874 scroll, 1.f / active_tree_->total_page_scale_factor()));
1877 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time,
1878 base::Time wall_clock_time) {
1879 if (!settings_.accelerated_animation_enabled ||
1880 animation_registrar_->active_animation_controllers().empty() ||
1881 !active_tree_->root_layer())
1882 return;
1884 TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers");
1886 last_animation_time_ = wall_clock_time;
1887 double monotonic_seconds = (monotonic_time - base::TimeTicks()).InSecondsF();
1889 AnimationRegistrar::AnimationControllerMap copy =
1890 animation_registrar_->active_animation_controllers();
1891 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1892 iter != copy.end();
1893 ++iter)
1894 (*iter).second->Animate(monotonic_seconds);
1896 client_->SetNeedsRedrawOnImplThread();
1899 void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
1900 if (!settings_.accelerated_animation_enabled ||
1901 animation_registrar_->active_animation_controllers().empty() ||
1902 !active_tree_->root_layer())
1903 return;
1905 TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState");
1906 scoped_ptr<AnimationEventsVector> events =
1907 make_scoped_ptr(new AnimationEventsVector);
1908 AnimationRegistrar::AnimationControllerMap copy =
1909 animation_registrar_->active_animation_controllers();
1910 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1911 iter != copy.end();
1912 ++iter)
1913 (*iter).second->UpdateState(start_ready_animations, events.get());
1915 if (!events->empty()) {
1916 client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass(),
1917 last_animation_time_);
1921 base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const {
1922 return base::TimeDelta::FromSeconds(1);
1925 void LayerTreeHostImpl::SendDidLoseOutputSurfaceRecursive(LayerImpl* current) {
1926 DCHECK(current);
1927 current->DidLoseOutputSurface();
1928 if (current->mask_layer())
1929 SendDidLoseOutputSurfaceRecursive(current->mask_layer());
1930 if (current->replica_layer())
1931 SendDidLoseOutputSurfaceRecursive(current->replica_layer());
1932 for (size_t i = 0; i < current->children().size(); ++i)
1933 SendDidLoseOutputSurfaceRecursive(current->children()[i]);
1936 void LayerTreeHostImpl::ClearRenderSurfaces() {
1937 active_tree_->ClearRenderSurfaces();
1938 if (pending_tree_)
1939 pending_tree_->ClearRenderSurfaces();
1942 std::string LayerTreeHostImpl::LayerTreeAsText() const {
1943 std::string str;
1944 if (active_tree_->root_layer()) {
1945 str = active_tree_->root_layer()->LayerTreeAsText();
1946 str += "RenderSurfaces:\n";
1947 DumpRenderSurfaces(&str, 1, active_tree_->root_layer());
1949 return str;
1952 std::string LayerTreeHostImpl::LayerTreeAsJson() const {
1953 std::string str;
1954 if (active_tree_->root_layer()) {
1955 scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson());
1956 base::JSONWriter::WriteWithOptions(
1957 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str);
1959 return str;
1962 void LayerTreeHostImpl::DumpRenderSurfaces(std::string* str,
1963 int indent,
1964 const LayerImpl* layer) const {
1965 if (layer->render_surface())
1966 layer->render_surface()->DumpSurface(str, indent);
1968 for (size_t i = 0; i < layer->children().size(); ++i)
1969 DumpRenderSurfaces(str, indent, layer->children()[i]);
1972 int LayerTreeHostImpl::SourceAnimationFrameNumber() const {
1973 return fps_counter_->current_frame_number();
1976 void LayerTreeHostImpl::SendManagedMemoryStats(
1977 size_t memory_visible_bytes,
1978 size_t memory_visible_and_nearby_bytes,
1979 size_t memory_use_bytes) {
1980 if (!renderer_)
1981 return;
1983 // Round the numbers being sent up to the next 8MB, to throttle the rate
1984 // at which we spam the GPU process.
1985 static const size_t rounding_step = 8 * 1024 * 1024;
1986 memory_visible_bytes = RoundUp(memory_visible_bytes, rounding_step);
1987 memory_visible_and_nearby_bytes = RoundUp(memory_visible_and_nearby_bytes,
1988 rounding_step);
1989 memory_use_bytes = RoundUp(memory_use_bytes, rounding_step);
1990 if (last_sent_memory_visible_bytes_ == memory_visible_bytes &&
1991 last_sent_memory_visible_and_nearby_bytes_ ==
1992 memory_visible_and_nearby_bytes &&
1993 last_sent_memory_use_bytes_ == memory_use_bytes) {
1994 return;
1996 last_sent_memory_visible_bytes_ = memory_visible_bytes;
1997 last_sent_memory_visible_and_nearby_bytes_ = memory_visible_and_nearby_bytes;
1998 last_sent_memory_use_bytes_ = memory_use_bytes;
2000 renderer_->SendManagedMemoryStats(last_sent_memory_visible_bytes_,
2001 last_sent_memory_visible_and_nearby_bytes_,
2002 last_sent_memory_use_bytes_);
2005 void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) {
2006 AnimateScrollbarsRecursive(active_tree_->root_layer(), time);
2009 void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer,
2010 base::TimeTicks time) {
2011 if (!layer)
2012 return;
2014 ScrollbarAnimationController* scrollbar_controller =
2015 layer->scrollbar_animation_controller();
2016 if (scrollbar_controller && scrollbar_controller->Animate(time)) {
2017 TRACE_EVENT_INSTANT0(
2018 "cc", "LayerTreeHostImpl::SetNeedsRedraw due to AnimateScrollbars",
2019 TRACE_EVENT_SCOPE_THREAD);
2020 client_->SetNeedsRedrawOnImplThread();
2023 for (size_t i = 0; i < layer->children().size(); ++i)
2024 AnimateScrollbarsRecursive(layer->children()[i], time);
2027 void LayerTreeHostImpl::StartScrollbarAnimation(base::TimeTicks time) {
2028 TRACE_EVENT0("cc", "LayerTreeHostImpl::StartScrollbarAnimation");
2029 StartScrollbarAnimationRecursive(RootLayer(), time);
2032 void LayerTreeHostImpl::StartScrollbarAnimationRecursive(LayerImpl* layer,
2033 base::TimeTicks time) {
2034 if (!layer)
2035 return;
2037 ScrollbarAnimationController* scrollbar_controller =
2038 layer->scrollbar_animation_controller();
2039 if (scrollbar_controller && scrollbar_controller->IsAnimating()) {
2040 base::TimeDelta delay = scrollbar_controller->DelayBeforeStart(time);
2041 if (delay > base::TimeDelta())
2042 client_->RequestScrollbarAnimationOnImplThread(delay);
2043 else if (scrollbar_controller->Animate(time))
2044 client_->SetNeedsRedrawOnImplThread();
2047 for (size_t i = 0; i < layer->children().size(); ++i)
2048 StartScrollbarAnimationRecursive(layer->children()[i], time);
2051 void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
2052 if (!tile_manager_)
2053 return;
2055 GlobalStateThatImpactsTilePriority new_state(tile_manager_->GlobalState());
2056 if (new_state.tree_priority == priority)
2057 return;
2059 new_state.tree_priority = priority;
2060 tile_manager_->SetGlobalState(new_state);
2063 void LayerTreeHostImpl::BeginNextFrame() {
2064 current_frame_timeticks_ = base::TimeTicks();
2065 current_frame_time_ = base::Time();
2068 static void UpdateCurrentFrameTime(base::TimeTicks* ticks, base::Time* now) {
2069 if (ticks->is_null()) {
2070 DCHECK(now->is_null());
2071 *ticks = base::TimeTicks::Now();
2072 *now = base::Time::Now();
2076 base::TimeTicks LayerTreeHostImpl::CurrentFrameTimeTicks() {
2077 UpdateCurrentFrameTime(&current_frame_timeticks_, &current_frame_time_);
2078 return current_frame_timeticks_;
2081 base::Time LayerTreeHostImpl::CurrentFrameTime() {
2082 UpdateCurrentFrameTime(&current_frame_timeticks_, &current_frame_time_);
2083 return current_frame_time_;
2086 scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const {
2087 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
2088 state->Set("activation_state", ActivationStateAsValue().release());
2089 state->Set("frame_state", FrameStateAsValue().release());
2090 return state.PassAs<base::Value>();
2093 scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const {
2094 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
2095 state->SetString("lthi_id", base::StringPrintf("%p", this));
2096 state->SetBoolean("visible_resources_ready",
2097 pending_tree_->AreVisibleResourcesReady());
2098 state->Set("tile_manager", tile_manager_->BasicStateAsValue().release());
2099 return state.PassAs<base::Value>();
2102 scoped_ptr<base::Value> LayerTreeHostImpl::FrameStateAsValue() const {
2103 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
2104 state->SetString("lthi_id", base::StringPrintf("%p", this));
2105 state->Set("device_viewport_size",
2106 MathUtil::AsValue(device_viewport_size_).release());
2107 if (tile_manager_)
2108 state->Set("tiles", tile_manager_->AllTilesAsValue().release());
2109 state->Set("active_tree", active_tree_->AsValue().release());
2110 return state.PassAs<base::Value>();
2113 // static
2114 LayerImpl* LayerTreeHostImpl::GetNonCompositedContentLayerRecursive(
2115 LayerImpl* layer) {
2116 if (!layer)
2117 return NULL;
2119 if (layer->DrawsContent())
2120 return layer;
2122 for (LayerImplList::const_iterator it = layer->children().begin();
2123 it != layer->children().end(); ++it) {
2124 LayerImpl* nccr = GetNonCompositedContentLayerRecursive(*it);
2125 if (nccr)
2126 return nccr;
2129 return NULL;
2132 skia::RefPtr<SkPicture> LayerTreeHostImpl::CapturePicture() {
2133 LayerTreeImpl* tree =
2134 pending_tree_ ? pending_tree_.get() : active_tree_.get();
2135 LayerImpl* layer = GetNonCompositedContentLayerRecursive(tree->root_layer());
2136 return layer ? layer->GetPicture() : skia::RefPtr<SkPicture>();
2139 void LayerTreeHostImpl::SetDebugState(const LayerTreeDebugState& debug_state) {
2140 if (debug_state_.continuous_painting != debug_state.continuous_painting)
2141 paint_time_counter_->ClearHistory();
2143 debug_state_ = debug_state;
2146 } // namespace cc