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.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/message_loop.h"
14 #include "base/stl_util.h"
15 #include "base/string_number_conversions.h"
16 #include "cc/animation/animation_registrar.h"
17 #include "cc/animation/layer_animation_controller.h"
18 #include "cc/base/math_util.h"
19 #include "cc/base/thread.h"
20 #include "cc/debug/overdraw_metrics.h"
21 #include "cc/debug/rendering_stats_instrumentation.h"
22 #include "cc/input/pinch_zoom_scrollbar.h"
23 #include "cc/input/pinch_zoom_scrollbar_geometry.h"
24 #include "cc/input/pinch_zoom_scrollbar_painter.h"
25 #include "cc/input/top_controls_manager.h"
26 #include "cc/layers/heads_up_display_layer.h"
27 #include "cc/layers/heads_up_display_layer_impl.h"
28 #include "cc/layers/layer.h"
29 #include "cc/layers/layer_iterator.h"
30 #include "cc/layers/render_surface.h"
31 #include "cc/layers/scrollbar_layer.h"
32 #include "cc/resources/prioritized_resource_manager.h"
33 #include "cc/trees/layer_tree_host_client.h"
34 #include "cc/trees/layer_tree_host_common.h"
35 #include "cc/trees/layer_tree_host_impl.h"
36 #include "cc/trees/layer_tree_impl.h"
37 #include "cc/trees/occlusion_tracker.h"
38 #include "cc/trees/single_thread_proxy.h"
39 #include "cc/trees/thread_proxy.h"
40 #include "cc/trees/tree_synchronizer.h"
41 #include "ui/gfx/size_conversions.h"
44 static int s_num_layer_tree_instances
;
49 RendererCapabilities::RendererCapabilities()
50 : best_texture_format(0),
51 using_partial_swap(false),
52 using_accelerated_painting(false),
53 using_set_visibility(false),
54 using_swap_complete_callback(false),
55 using_gpu_memory_manager(false),
56 using_egl_image(false),
57 allow_partial_texture_updates(false),
58 using_offscreen_context3d(false),
60 avoid_pow2_textures(false) {}
62 RendererCapabilities::~RendererCapabilities() {}
64 bool LayerTreeHost::AnyLayerTreeHostInstanceExists() {
65 return s_num_layer_tree_instances
> 0;
68 scoped_ptr
<LayerTreeHost
> LayerTreeHost::Create(
69 LayerTreeHostClient
* client
,
70 const LayerTreeSettings
& settings
,
71 scoped_ptr
<Thread
> impl_thread
) {
72 scoped_ptr
<LayerTreeHost
> layer_tree_host(new LayerTreeHost(client
,
74 if (!layer_tree_host
->Initialize(impl_thread
.Pass()))
75 return scoped_ptr
<LayerTreeHost
>();
76 return layer_tree_host
.Pass();
79 LayerTreeHost::LayerTreeHost(LayerTreeHostClient
* client
,
80 const LayerTreeSettings
& settings
)
82 needs_full_tree_sync_(true),
83 needs_filter_context_(false),
86 rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
87 renderer_can_be_initialized_(true),
88 renderer_initialized_(false),
89 output_surface_lost_(false),
90 num_failed_recreate_attempts_(0),
92 debug_state_(settings
.initial_debug_state
),
93 overdraw_bottom_height_(0.f
),
94 device_scale_factor_(1.f
),
96 page_scale_factor_(1.f
),
97 min_page_scale_factor_(1.f
),
98 max_page_scale_factor_(1.f
),
99 trigger_idle_updates_(true),
100 background_color_(SK_ColorWHITE
),
101 has_transparent_background_(false),
102 partial_texture_update_requests_(0),
103 in_paint_layer_contents_(false) {
104 if (settings_
.accelerated_animation_enabled
)
105 animation_registrar_
= AnimationRegistrar::Create();
106 s_num_layer_tree_instances
++;
108 rendering_stats_instrumentation_
->set_record_rendering_stats(
109 debug_state_
.RecordRenderingStats());
112 bool LayerTreeHost::Initialize(scoped_ptr
<Thread
> impl_thread
) {
114 return InitializeProxy(ThreadProxy::Create(this, impl_thread
.Pass()));
116 return InitializeProxy(SingleThreadProxy::Create(this));
119 bool LayerTreeHost::InitializeForTesting(scoped_ptr
<Proxy
> proxy_for_testing
) {
120 return InitializeProxy(proxy_for_testing
.Pass());
123 bool LayerTreeHost::InitializeProxy(scoped_ptr
<Proxy
> proxy
) {
124 TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal");
126 proxy_
= proxy
.Pass();
128 return proxy_
->InitializeOutputSurface();
131 LayerTreeHost::~LayerTreeHost() {
133 root_layer_
->SetLayerTreeHost(NULL
);
135 DCHECK(proxy_
->IsMainThread());
136 TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
138 s_num_layer_tree_instances
--;
139 RateLimiterMap::iterator it
= rate_limiters_
.begin();
140 if (it
!= rate_limiters_
.end())
144 // The layer tree must be destroyed before the layer tree host. We've
145 // made a contract with our animation controllers that the registrar
146 // will outlive them, and we must make good.
151 void LayerTreeHost::SetSurfaceReady() {
152 proxy_
->SetSurfaceReady();
155 void LayerTreeHost::InitializeRenderer() {
156 TRACE_EVENT0("cc", "LayerTreeHost::InitializeRenderer");
157 if (!proxy_
->InitializeRenderer()) {
158 // Uh oh, better tell the client that we can't do anything with this output
160 renderer_can_be_initialized_
= false;
161 client_
->DidRecreateOutputSurface(false);
165 // Update settings_ based on capabilities that we got back from the renderer.
166 settings_
.accelerate_painting
=
167 proxy_
->GetRendererCapabilities().using_accelerated_painting
;
169 // Update settings_ based on partial update capability.
170 size_t max_partial_texture_updates
= 0;
171 if (proxy_
->GetRendererCapabilities().allow_partial_texture_updates
&&
172 !settings_
.impl_side_painting
) {
173 max_partial_texture_updates
= std::min(
174 settings_
.max_partial_texture_updates
,
175 proxy_
->MaxPartialTextureUpdates());
177 settings_
.max_partial_texture_updates
= max_partial_texture_updates
;
179 contents_texture_manager_
= PrioritizedResourceManager::Create(proxy_
.get());
180 surface_memory_placeholder_
=
181 contents_texture_manager_
->CreateTexture(gfx::Size(), GL_RGBA
);
183 renderer_initialized_
= true;
186 LayerTreeHost::RecreateResult
LayerTreeHost::RecreateOutputSurface() {
187 TRACE_EVENT0("cc", "LayerTreeHost::RecreateOutputSurface");
188 DCHECK(output_surface_lost_
);
190 if (proxy_
->RecreateOutputSurface()) {
191 client_
->DidRecreateOutputSurface(true);
192 output_surface_lost_
= false;
193 return RecreateSucceeded
;
196 client_
->WillRetryRecreateOutputSurface();
198 // Tolerate a certain number of recreation failures to work around races
199 // in the output-surface-lost machinery.
200 num_failed_recreate_attempts_
++;
201 if (num_failed_recreate_attempts_
< 5) {
202 // FIXME: The single thread does not self-schedule output surface
203 // recreation. So force another recreation attempt to happen by requesting
205 if (!proxy_
->HasImplThread())
207 return RecreateFailedButTryAgain
;
210 // We have tried too many times to recreate the output surface. Tell the
211 // host to fall back to software rendering.
212 renderer_can_be_initialized_
= false;
213 client_
->DidRecreateOutputSurface(false);
214 return RecreateFailedAndGaveUp
;
217 void LayerTreeHost::DeleteContentsTexturesOnImplThread(
218 ResourceProvider
* resource_provider
) {
219 DCHECK(proxy_
->IsImplThread());
220 if (renderer_initialized_
)
221 contents_texture_manager_
->ClearAllMemory(resource_provider
);
224 void LayerTreeHost::AcquireLayerTextures() {
225 DCHECK(proxy_
->IsMainThread());
226 proxy_
->AcquireLayerTextures();
229 void LayerTreeHost::DidBeginFrame() {
230 client_
->DidBeginFrame();
233 void LayerTreeHost::UpdateAnimations(base::TimeTicks frame_begin_time
) {
235 client_
->Animate((frame_begin_time
- base::TimeTicks()).InSecondsF());
236 AnimateLayers(frame_begin_time
);
239 rendering_stats_instrumentation_
->IncrementAnimationFrameCount();
242 void LayerTreeHost::DidStopFlinging() {
243 proxy_
->MainThreadHasStoppedFlinging();
246 void LayerTreeHost::Layout() {
250 void LayerTreeHost::BeginCommitOnImplThread(LayerTreeHostImpl
* host_impl
) {
251 DCHECK(proxy_
->IsImplThread());
252 TRACE_EVENT0("cc", "LayerTreeHost::CommitTo");
255 // This function commits the LayerTreeHost to an impl tree. When modifying
256 // this function, keep in mind that the function *runs* on the impl thread! Any
257 // code that is logically a main thread operation, e.g. deletion of a Layer,
258 // should be delayed until the LayerTreeHost::CommitComplete, which will run
259 // after the commit, but on the main thread.
260 void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl
* host_impl
) {
261 DCHECK(proxy_
->IsImplThread());
263 // If there are linked evicted backings, these backings' resources may be put
264 // into the impl tree, so we can't draw yet. Determine this before clearing
265 // all evicted backings.
266 bool new_impl_tree_has_no_evicted_resources
=
267 !contents_texture_manager_
->LinkedEvictedBackingsExist();
269 // If the memory limit has been increased since this now-finishing
270 // commit began, and the extra now-available memory would have been used,
271 // then request another commit.
272 if (contents_texture_manager_
->MaxMemoryLimitBytes() <
273 host_impl
->memory_allocation_limit_bytes() &&
274 contents_texture_manager_
->MaxMemoryLimitBytes() <
275 contents_texture_manager_
->MaxMemoryNeededBytes()) {
276 host_impl
->SetNeedsCommit();
279 host_impl
->set_max_memory_needed_bytes(
280 contents_texture_manager_
->MaxMemoryNeededBytes());
282 contents_texture_manager_
->UpdateBackingsInDrawingImplTree();
284 // In impl-side painting, synchronize to the pending tree so that it has
285 // time to raster before being displayed. If no pending tree is needed,
286 // synchronization can happen directly to the active tree and
287 // unlinked contents resources can be reclaimed immediately.
288 LayerTreeImpl
* sync_tree
;
289 if (settings_
.impl_side_painting
) {
290 // Commits should not occur while there is already a pending tree.
291 DCHECK(!host_impl
->pending_tree());
292 host_impl
->CreatePendingTree();
293 sync_tree
= host_impl
->pending_tree();
295 contents_texture_manager_
->ReduceMemory(host_impl
->resource_provider());
296 sync_tree
= host_impl
->active_tree();
299 if (needs_full_tree_sync_
)
300 sync_tree
->SetRootLayer(TreeSynchronizer::SynchronizeTrees(
301 root_layer(), sync_tree
->DetachLayerTree(), sync_tree
));
303 TRACE_EVENT0("cc", "LayerTreeHost::PushProperties");
304 TreeSynchronizer::PushProperties(root_layer(), sync_tree
->root_layer());
307 sync_tree
->set_needs_full_tree_sync(needs_full_tree_sync_
);
308 needs_full_tree_sync_
= false;
310 if (root_layer_
&& hud_layer_
) {
311 LayerImpl
* hud_impl
= LayerTreeHostCommon::FindLayerInSubtree(
312 sync_tree
->root_layer(), hud_layer_
->id());
313 sync_tree
->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl
*>(hud_impl
));
315 sync_tree
->set_hud_layer(NULL
);
318 sync_tree
->set_source_frame_number(commit_number());
319 sync_tree
->set_background_color(background_color_
);
320 sync_tree
->set_has_transparent_background(has_transparent_background_
);
322 sync_tree
->FindRootScrollLayer();
324 float page_scale_delta
, sent_page_scale_delta
;
325 if (settings_
.impl_side_painting
) {
326 // Update the delta from the active tree, which may have
327 // adjusted its delta prior to the pending tree being created.
328 // This code is equivalent to that in LayerTreeImpl::SetPageScaleDelta.
329 DCHECK_EQ(1.f
, sync_tree
->sent_page_scale_delta());
330 page_scale_delta
= host_impl
->active_tree()->page_scale_delta();
331 sent_page_scale_delta
= host_impl
->active_tree()->sent_page_scale_delta();
333 page_scale_delta
= sync_tree
->page_scale_delta();
334 sent_page_scale_delta
= sync_tree
->sent_page_scale_delta();
335 sync_tree
->set_sent_page_scale_delta(1.f
);
338 sync_tree
->SetPageScaleFactorAndLimits(page_scale_factor_
,
339 min_page_scale_factor_
,
340 max_page_scale_factor_
);
341 sync_tree
->SetPageScaleDelta(page_scale_delta
/ sent_page_scale_delta
);
342 sync_tree
->SetLatencyInfo(latency_info_
);
343 latency_info_
.Clear();
345 host_impl
->SetViewportSize(device_viewport_size_
);
346 host_impl
->SetOverdrawBottomHeight(overdraw_bottom_height_
);
347 host_impl
->SetDeviceScaleFactor(device_scale_factor_
);
348 host_impl
->SetDebugState(debug_state_
);
349 if (pending_page_scale_animation_
) {
350 host_impl
->StartPageScaleAnimation(
351 pending_page_scale_animation_
->target_offset
,
352 pending_page_scale_animation_
->use_anchor
,
353 pending_page_scale_animation_
->scale
,
354 base::TimeTicks::Now(),
355 pending_page_scale_animation_
->duration
);
356 pending_page_scale_animation_
.reset();
359 DCHECK(!sync_tree
->ViewportSizeInvalid());
361 if (new_impl_tree_has_no_evicted_resources
) {
362 if (sync_tree
->ContentsTexturesPurged())
363 sync_tree
->ResetContentsTexturesPurged();
366 sync_tree
->SetPinchZoomHorizontalLayerId(
367 pinch_zoom_scrollbar_horizontal_
?
368 pinch_zoom_scrollbar_horizontal_
->id() : Layer::INVALID_ID
);
370 sync_tree
->SetPinchZoomVerticalLayerId(
371 pinch_zoom_scrollbar_vertical_
?
372 pinch_zoom_scrollbar_vertical_
->id() : Layer::INVALID_ID
);
374 if (!settings_
.impl_side_painting
) {
375 // If we're not in impl-side painting, the tree is immediately
376 // considered active.
377 sync_tree
->DidBecomeActive();
383 gfx::Size
LayerTreeHost::PinchZoomScrollbarSize(
384 WebKit::WebScrollbar::Orientation orientation
) const {
385 gfx::Size viewport_size
= gfx::ToCeiledSize(
386 gfx::ScaleSize(device_viewport_size(), 1.f
/ device_scale_factor()));
388 int track_width
= PinchZoomScrollbarGeometry::kTrackWidth
;
389 if (orientation
== WebKit::WebScrollbar::Horizontal
)
390 size
= gfx::Size(viewport_size
.width() - track_width
, track_width
);
392 size
= gfx::Size(track_width
, viewport_size
.height() - track_width
);
396 void LayerTreeHost::SetPinchZoomScrollbarsBoundsAndPosition() {
397 if (!pinch_zoom_scrollbar_horizontal_
|| !pinch_zoom_scrollbar_vertical_
)
400 gfx::Size horizontal_size
=
401 PinchZoomScrollbarSize(WebKit::WebScrollbar::Horizontal
);
402 gfx::Size vertical_size
=
403 PinchZoomScrollbarSize(WebKit::WebScrollbar::Vertical
);
405 pinch_zoom_scrollbar_horizontal_
->SetBounds(horizontal_size
);
406 pinch_zoom_scrollbar_horizontal_
->SetPosition(
407 gfx::PointF(0, vertical_size
.height()));
408 pinch_zoom_scrollbar_vertical_
->SetBounds(vertical_size
);
409 pinch_zoom_scrollbar_vertical_
->SetPosition(
410 gfx::PointF(horizontal_size
.width(), 0));
413 static scoped_refptr
<ScrollbarLayer
> CreatePinchZoomScrollbar(
414 WebKit::WebScrollbar::Orientation orientation
,
415 LayerTreeHost
* owner
) {
416 scoped_refptr
<ScrollbarLayer
> scrollbar_layer
= ScrollbarLayer::Create(
417 make_scoped_ptr(new PinchZoomScrollbar(orientation
, owner
)).
418 PassAs
<WebKit::WebScrollbar
>(),
419 scoped_ptr
<ScrollbarThemePainter
>(new PinchZoomScrollbarPainter
).Pass(),
420 scoped_ptr
<WebKit::WebScrollbarThemeGeometry
>(
421 new PinchZoomScrollbarGeometry
).Pass(),
422 Layer::PINCH_ZOOM_ROOT_SCROLL_LAYER_ID
);
423 scrollbar_layer
->SetIsDrawable(true);
424 scrollbar_layer
->SetOpacity(0.f
);
425 return scrollbar_layer
;
428 void LayerTreeHost::CreateAndAddPinchZoomScrollbars() {
429 bool needs_properties_updated
= false;
431 if (!pinch_zoom_scrollbar_horizontal_
|| !pinch_zoom_scrollbar_vertical_
) {
432 pinch_zoom_scrollbar_horizontal_
=
433 CreatePinchZoomScrollbar(WebKit::WebScrollbar::Horizontal
, this);
434 pinch_zoom_scrollbar_vertical_
=
435 CreatePinchZoomScrollbar(WebKit::WebScrollbar::Vertical
, this);
436 needs_properties_updated
= true;
439 DCHECK(pinch_zoom_scrollbar_horizontal_
&& pinch_zoom_scrollbar_vertical_
);
441 if (!pinch_zoom_scrollbar_horizontal_
->parent())
442 root_layer_
->AddChild(pinch_zoom_scrollbar_horizontal_
);
444 if (!pinch_zoom_scrollbar_vertical_
->parent())
445 root_layer_
->AddChild(pinch_zoom_scrollbar_vertical_
);
447 if (needs_properties_updated
)
448 SetPinchZoomScrollbarsBoundsAndPosition();
451 void LayerTreeHost::WillCommit() {
452 client_
->WillCommit();
454 if (settings().use_pinch_zoom_scrollbars
)
455 CreateAndAddPinchZoomScrollbars();
458 void LayerTreeHost::UpdateHudLayer() {
459 if (debug_state_
.ShowHudInfo()) {
461 hud_layer_
= HeadsUpDisplayLayer::Create();
463 if (root_layer_
&& !hud_layer_
->parent())
464 root_layer_
->AddChild(hud_layer_
);
465 } else if (hud_layer_
) {
466 hud_layer_
->RemoveFromParent();
471 void LayerTreeHost::CommitComplete() {
472 client_
->DidCommit();
475 scoped_ptr
<OutputSurface
> LayerTreeHost::CreateOutputSurface() {
476 return client_
->CreateOutputSurface();
479 scoped_ptr
<InputHandler
> LayerTreeHost::CreateInputHandler() {
480 return client_
->CreateInputHandler();
483 scoped_ptr
<LayerTreeHostImpl
> LayerTreeHost::CreateLayerTreeHostImpl(
484 LayerTreeHostImplClient
* client
) {
485 DCHECK(proxy_
->IsImplThread());
486 scoped_ptr
<LayerTreeHostImpl
> host_impl
=
487 LayerTreeHostImpl::Create(settings_
,
490 rendering_stats_instrumentation_
.get());
491 if (settings_
.calculate_top_controls_position
&&
492 host_impl
->top_controls_manager()) {
493 top_controls_manager_weak_ptr_
=
494 host_impl
->top_controls_manager()->AsWeakPtr();
496 return host_impl
.Pass();
499 void LayerTreeHost::DidLoseOutputSurface() {
500 TRACE_EVENT0("cc", "LayerTreeHost::DidLoseOutputSurface");
501 DCHECK(proxy_
->IsMainThread());
502 output_surface_lost_
= true;
503 num_failed_recreate_attempts_
= 0;
507 bool LayerTreeHost::CompositeAndReadback(void* pixels
,
508 gfx::Rect rect_in_device_viewport
) {
509 trigger_idle_updates_
= false;
510 bool ret
= proxy_
->CompositeAndReadback(pixels
, rect_in_device_viewport
);
511 trigger_idle_updates_
= true;
515 void LayerTreeHost::FinishAllRendering() {
516 if (!renderer_initialized_
)
518 proxy_
->FinishAllRendering();
521 void LayerTreeHost::SetDeferCommits(bool defer_commits
) {
522 proxy_
->SetDeferCommits(defer_commits
);
525 void LayerTreeHost::DidDeferCommit() {}
527 void LayerTreeHost::SetNeedsDisplayOnAllLayers() {
528 std::stack
<Layer
*> layer_stack
;
529 layer_stack
.push(root_layer());
530 while (!layer_stack
.empty()) {
531 Layer
* current_layer
= layer_stack
.top();
533 current_layer
->SetNeedsDisplay();
534 for (unsigned int i
= 0; i
< current_layer
->children().size(); i
++) {
535 layer_stack
.push(current_layer
->child_at(i
));
540 void LayerTreeHost::CollectRenderingStats(RenderingStats
* stats
) const {
541 CHECK(debug_state_
.RecordRenderingStats());
542 *stats
= rendering_stats_instrumentation_
->GetRenderingStats();
545 const RendererCapabilities
& LayerTreeHost::GetRendererCapabilities() const {
546 return proxy_
->GetRendererCapabilities();
549 void LayerTreeHost::SetNeedsAnimate() {
550 DCHECK(proxy_
->HasImplThread());
551 proxy_
->SetNeedsAnimate();
554 void LayerTreeHost::SetNeedsCommit() {
555 if (!prepaint_callback_
.IsCancelled()) {
556 TRACE_EVENT_INSTANT0("cc",
557 "LayerTreeHost::SetNeedsCommit::cancel prepaint",
558 TRACE_EVENT_SCOPE_THREAD
);
559 prepaint_callback_
.Cancel();
561 proxy_
->SetNeedsCommit();
564 void LayerTreeHost::SetNeedsFullTreeSync() {
565 needs_full_tree_sync_
= true;
569 void LayerTreeHost::SetNeedsRedraw() {
570 SetNeedsRedrawRect(gfx::Rect(device_viewport_size_
));
573 void LayerTreeHost::SetNeedsRedrawRect(gfx::Rect damage_rect
) {
574 proxy_
->SetNeedsRedraw(damage_rect
);
575 if (!proxy_
->ImplThread())
576 client_
->ScheduleComposite();
579 bool LayerTreeHost::CommitRequested() const {
580 return proxy_
->CommitRequested();
583 void LayerTreeHost::SetAnimationEvents(scoped_ptr
<AnimationEventsVector
> events
,
584 base::Time wall_clock_time
) {
585 DCHECK(proxy_
->IsMainThread());
586 for (size_t event_index
= 0; event_index
< events
->size(); ++event_index
) {
587 int event_layer_id
= (*events
)[event_index
].layer_id
;
589 // Use the map of all controllers, not just active ones, since non-active
590 // controllers may still receive events for impl-only animations.
591 const AnimationRegistrar::AnimationControllerMap
& animation_controllers
=
592 animation_registrar_
->all_animation_controllers();
593 AnimationRegistrar::AnimationControllerMap::const_iterator iter
=
594 animation_controllers
.find(event_layer_id
);
595 if (iter
!= animation_controllers
.end()) {
596 switch ((*events
)[event_index
].type
) {
597 case AnimationEvent::Started
:
598 (*iter
).second
->NotifyAnimationStarted((*events
)[event_index
],
599 wall_clock_time
.ToDoubleT());
602 case AnimationEvent::Finished
:
603 (*iter
).second
->NotifyAnimationFinished((*events
)[event_index
],
604 wall_clock_time
.ToDoubleT());
607 case AnimationEvent::PropertyUpdate
:
608 (*iter
).second
->NotifyAnimationPropertyUpdate((*events
)[event_index
]);
618 void LayerTreeHost::SetRootLayer(scoped_refptr
<Layer
> root_layer
) {
619 if (root_layer_
== root_layer
)
623 root_layer_
->SetLayerTreeHost(NULL
);
624 root_layer_
= root_layer
;
626 root_layer_
->SetLayerTreeHost(this);
629 hud_layer_
->RemoveFromParent();
631 if (pinch_zoom_scrollbar_horizontal_
)
632 pinch_zoom_scrollbar_horizontal_
->RemoveFromParent();
634 if (pinch_zoom_scrollbar_vertical_
)
635 pinch_zoom_scrollbar_vertical_
->RemoveFromParent();
637 SetNeedsFullTreeSync();
640 void LayerTreeHost::SetDebugState(const LayerTreeDebugState
& debug_state
) {
641 LayerTreeDebugState new_debug_state
=
642 LayerTreeDebugState::Unite(settings_
.initial_debug_state
, debug_state
);
644 if (LayerTreeDebugState::Equal(debug_state_
, new_debug_state
))
647 debug_state_
= new_debug_state
;
649 rendering_stats_instrumentation_
->set_record_rendering_stats(
650 debug_state_
.RecordRenderingStats());
655 void LayerTreeHost::SetViewportSize(gfx::Size device_viewport_size
) {
656 if (device_viewport_size
== device_viewport_size_
)
659 device_viewport_size_
= device_viewport_size
;
661 SetPinchZoomScrollbarsBoundsAndPosition();
665 void LayerTreeHost::SetOverdrawBottomHeight(float overdraw_bottom_height
) {
666 if (overdraw_bottom_height_
== overdraw_bottom_height
)
669 overdraw_bottom_height_
= overdraw_bottom_height
;
673 void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor
,
674 float min_page_scale_factor
,
675 float max_page_scale_factor
) {
676 if (page_scale_factor
== page_scale_factor_
&&
677 min_page_scale_factor
== min_page_scale_factor_
&&
678 max_page_scale_factor
== max_page_scale_factor_
)
681 page_scale_factor_
= page_scale_factor
;
682 min_page_scale_factor_
= min_page_scale_factor
;
683 max_page_scale_factor_
= max_page_scale_factor
;
687 void LayerTreeHost::SetVisible(bool visible
) {
688 if (visible_
== visible
)
691 proxy_
->SetVisible(visible
);
694 void LayerTreeHost::SetLatencyInfo(const LatencyInfo
& latency_info
) {
695 latency_info_
.MergeWith(latency_info
);
698 void LayerTreeHost::StartPageScaleAnimation(gfx::Vector2d target_offset
,
701 base::TimeDelta duration
) {
702 pending_page_scale_animation_
.reset(new PendingPageScaleAnimation
);
703 pending_page_scale_animation_
->target_offset
= target_offset
;
704 pending_page_scale_animation_
->use_anchor
= use_anchor
;
705 pending_page_scale_animation_
->scale
= scale
;
706 pending_page_scale_animation_
->duration
= duration
;
711 void LayerTreeHost::Composite(base::TimeTicks frame_begin_time
) {
712 if (!proxy_
->HasImplThread())
713 static_cast<SingleThreadProxy
*>(proxy_
.get())->CompositeImmediately(
719 void LayerTreeHost::ScheduleComposite() {
720 client_
->ScheduleComposite();
723 bool LayerTreeHost::InitializeRendererIfNeeded() {
724 if (!renderer_can_be_initialized_
)
727 if (!renderer_initialized_
) {
728 InitializeRenderer();
729 // If we couldn't initialize, then bail since we're returning to software
731 if (!renderer_initialized_
)
734 if (output_surface_lost_
) {
735 if (RecreateOutputSurface() != RecreateSucceeded
)
741 void LayerTreeHost::UpdateLayers(ResourceUpdateQueue
* queue
,
742 size_t memory_allocation_limit_bytes
) {
743 DCHECK(renderer_initialized_
);
748 if (device_viewport_size().IsEmpty())
751 if (memory_allocation_limit_bytes
) {
752 contents_texture_manager_
->SetMaxMemoryLimitBytes(
753 memory_allocation_limit_bytes
);
756 UpdateLayers(root_layer(), queue
);
759 static Layer
* FindFirstScrollableLayer(Layer
* layer
) {
763 if (layer
->scrollable())
766 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
767 Layer
* found
= FindFirstScrollableLayer(layer
->children()[i
].get());
775 const Layer
* LayerTreeHost::RootScrollLayer() const {
776 return FindFirstScrollableLayer(root_layer_
.get());
779 void LayerTreeHost::UpdateLayers(Layer
* root_layer
,
780 ResourceUpdateQueue
* queue
) {
781 TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers");
783 LayerList update_list
;
787 Layer
* root_scroll
= FindFirstScrollableLayer(root_layer
);
789 TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
790 LayerTreeHostCommon::CalculateDrawProperties(
792 device_viewport_size(),
793 device_scale_factor_
,
796 GetRendererCapabilities().max_texture_size
,
797 settings_
.can_use_lcd_text
,
801 // Reset partial texture update requests.
802 partial_texture_update_requests_
= 0;
804 bool need_more_updates
= PaintLayerContents(update_list
, queue
);
805 if (trigger_idle_updates_
&& need_more_updates
) {
806 TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::posting prepaint task");
807 prepaint_callback_
.Reset(base::Bind(&LayerTreeHost::TriggerPrepaint
,
808 base::Unretained(this)));
809 static base::TimeDelta prepaint_delay
=
810 base::TimeDelta::FromMilliseconds(100);
811 MessageLoop::current()->PostDelayedTask(FROM_HERE
,
812 prepaint_callback_
.callback(),
816 for (size_t i
= 0; i
< update_list
.size(); ++i
)
817 update_list
[i
]->ClearRenderSurface();
820 void LayerTreeHost::TriggerPrepaint() {
821 prepaint_callback_
.Cancel();
822 TRACE_EVENT0("cc", "LayerTreeHost::TriggerPrepaint");
826 void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes
) {
827 // Surfaces have a place holder for their memory since they are managed
828 // independantly but should still be tracked and reduce other memory usage.
829 surface_memory_placeholder_
->SetTextureManager(
830 contents_texture_manager_
.get());
831 surface_memory_placeholder_
->set_request_priority(
832 PriorityCalculator::RenderSurfacePriority());
833 surface_memory_placeholder_
->SetToSelfManagedMemoryPlaceholder(
834 surface_memory_bytes
);
837 void LayerTreeHost::SetPrioritiesForLayers(const LayerList
& update_list
) {
838 // Use BackToFront since it's cheap and this isn't order-dependent.
839 typedef LayerIterator
<Layer
,
842 LayerIteratorActions::BackToFront
> LayerIteratorType
;
844 PriorityCalculator calculator
;
845 LayerIteratorType end
= LayerIteratorType::End(&update_list
);
846 for (LayerIteratorType it
= LayerIteratorType::Begin(&update_list
);
849 if (it
.represents_itself()) {
850 it
->SetTexturePriorities(calculator
);
851 } else if (it
.represents_target_render_surface()) {
852 if (it
->mask_layer())
853 it
->mask_layer()->SetTexturePriorities(calculator
);
854 if (it
->replica_layer() && it
->replica_layer()->mask_layer())
855 it
->replica_layer()->mask_layer()->SetTexturePriorities(calculator
);
860 void LayerTreeHost::PrioritizeTextures(
861 const LayerList
& render_surface_layer_list
, OverdrawMetrics
* metrics
) {
862 contents_texture_manager_
->ClearPriorities();
864 size_t memory_for_render_surfaces_metric
=
865 CalculateMemoryForRenderSurfaces(render_surface_layer_list
);
867 SetPrioritiesForLayers(render_surface_layer_list
);
868 SetPrioritiesForSurfaces(memory_for_render_surfaces_metric
);
870 metrics
->DidUseContentsTextureMemoryBytes(
871 contents_texture_manager_
->MemoryAboveCutoffBytes());
872 metrics
->DidUseRenderSurfaceTextureMemoryBytes(
873 memory_for_render_surfaces_metric
);
875 contents_texture_manager_
->PrioritizeTextures();
878 size_t LayerTreeHost::CalculateMemoryForRenderSurfaces(
879 const LayerList
& update_list
) {
880 size_t readback_bytes
= 0;
881 size_t max_background_texture_bytes
= 0;
882 size_t contents_texture_bytes
= 0;
884 // Start iteration at 1 to skip the root surface as it does not have a texture
886 for (size_t i
= 1; i
< update_list
.size(); ++i
) {
887 Layer
* render_surface_layer
= update_list
[i
].get();
888 RenderSurface
* render_surface
= render_surface_layer
->render_surface();
891 Resource::MemorySizeBytes(render_surface
->content_rect().size(),
893 contents_texture_bytes
+= bytes
;
895 if (render_surface_layer
->background_filters().isEmpty())
898 if (bytes
> max_background_texture_bytes
)
899 max_background_texture_bytes
= bytes
;
900 if (!readback_bytes
) {
901 readback_bytes
= Resource::MemorySizeBytes(device_viewport_size_
,
905 return readback_bytes
+ max_background_texture_bytes
+ contents_texture_bytes
;
908 bool LayerTreeHost::PaintMasksForRenderSurface(Layer
* render_surface_layer
,
909 ResourceUpdateQueue
* queue
,
910 RenderingStats
* stats
) {
911 // Note: Masks and replicas only exist for layers that own render surfaces. If
912 // we reach this point in code, we already know that at least something will
913 // be drawn into this render surface, so the mask and replica should be
916 bool need_more_updates
= false;
917 Layer
* mask_layer
= render_surface_layer
->mask_layer();
919 mask_layer
->Update(queue
, NULL
, stats
);
920 need_more_updates
|= mask_layer
->NeedMoreUpdates();
923 Layer
* replica_mask_layer
=
924 render_surface_layer
->replica_layer() ?
925 render_surface_layer
->replica_layer()->mask_layer() : NULL
;
926 if (replica_mask_layer
) {
927 replica_mask_layer
->Update(queue
, NULL
, stats
);
928 need_more_updates
|= replica_mask_layer
->NeedMoreUpdates();
930 return need_more_updates
;
933 bool LayerTreeHost::PaintLayerContents(
934 const LayerList
& render_surface_layer_list
, ResourceUpdateQueue
* queue
) {
935 // Use FrontToBack to allow for testing occlusion and performing culling
936 // during the tree walk.
937 typedef LayerIterator
<Layer
,
940 LayerIteratorActions::FrontToBack
> LayerIteratorType
;
942 bool need_more_updates
= false;
943 bool record_metrics_for_frame
=
944 settings_
.show_overdraw_in_tracing
&&
945 base::debug::TraceLog::GetInstance() &&
946 base::debug::TraceLog::GetInstance()->IsEnabled();
947 OcclusionTracker
occlusion_tracker(
948 root_layer_
->render_surface()->content_rect(), record_metrics_for_frame
);
949 occlusion_tracker
.set_minimum_tracking_size(
950 settings_
.minimum_occlusion_tracking_size
);
952 PrioritizeTextures(render_surface_layer_list
,
953 occlusion_tracker
.overdraw_metrics());
955 // TODO(egraether): Use RenderingStatsInstrumentation in Layer::update()
956 RenderingStats stats
;
957 RenderingStats
* stats_ptr
=
958 debug_state_
.RecordRenderingStats() ? &stats
: NULL
;
960 in_paint_layer_contents_
= true;
962 LayerIteratorType end
= LayerIteratorType::End(&render_surface_layer_list
);
963 for (LayerIteratorType it
=
964 LayerIteratorType::Begin(&render_surface_layer_list
);
967 bool prevent_occlusion
=
968 it
.target_render_surface_layer()->HasRequestCopyCallback();
969 occlusion_tracker
.EnterLayer(it
, prevent_occlusion
);
971 if (it
.represents_target_render_surface()) {
972 DCHECK(it
->render_surface()->draw_opacity() ||
973 it
->render_surface()->draw_opacity_is_animating());
974 need_more_updates
|= PaintMasksForRenderSurface(*it
, queue
, stats_ptr
);
975 } else if (it
.represents_itself()) {
976 DCHECK(!it
->paint_properties().bounds
.IsEmpty());
977 it
->Update(queue
, &occlusion_tracker
, stats_ptr
);
978 need_more_updates
|= it
->NeedMoreUpdates();
981 occlusion_tracker
.LeaveLayer(it
);
984 in_paint_layer_contents_
= false;
986 rendering_stats_instrumentation_
->AddStats(stats
);
988 occlusion_tracker
.overdraw_metrics()->RecordMetrics(this);
990 return need_more_updates
;
993 void LayerTreeHost::ApplyScrollAndScale(const ScrollAndScaleSet
& info
) {
997 Layer
* root_scroll_layer
= FindFirstScrollableLayer(root_layer_
.get());
998 gfx::Vector2d root_scroll_delta
;
1000 for (size_t i
= 0; i
< info
.scrolls
.size(); ++i
) {
1002 LayerTreeHostCommon::FindLayerInSubtree(root_layer_
.get(),
1003 info
.scrolls
[i
].layer_id
);
1006 if (layer
== root_scroll_layer
)
1007 root_scroll_delta
+= info
.scrolls
[i
].scroll_delta
;
1009 layer
->SetScrollOffset(layer
->scroll_offset() +
1010 info
.scrolls
[i
].scroll_delta
);
1012 if (!root_scroll_delta
.IsZero() || info
.page_scale_delta
!= 1.f
)
1013 client_
->ApplyScrollAndScale(root_scroll_delta
, info
.page_scale_delta
);
1016 void LayerTreeHost::StartRateLimiter(WebKit::WebGraphicsContext3D
* context3d
) {
1021 RateLimiterMap::iterator it
= rate_limiters_
.find(context3d
);
1022 if (it
!= rate_limiters_
.end()) {
1023 it
->second
->Start();
1025 scoped_refptr
<RateLimiter
> rate_limiter
=
1026 RateLimiter::Create(context3d
, this, proxy_
->MainThread());
1027 rate_limiters_
[context3d
] = rate_limiter
;
1028 rate_limiter
->Start();
1032 void LayerTreeHost::StopRateLimiter(WebKit::WebGraphicsContext3D
* context3d
) {
1033 RateLimiterMap::iterator it
= rate_limiters_
.find(context3d
);
1034 if (it
!= rate_limiters_
.end()) {
1036 rate_limiters_
.erase(it
);
1040 void LayerTreeHost::RateLimit() {
1041 // Force a no-op command on the compositor context, so that any ratelimiting
1042 // commands will wait for the compositing context, and therefore for the
1044 proxy_
->ForceSerializeOnSwapBuffers();
1047 bool LayerTreeHost::RequestPartialTextureUpdate() {
1048 if (partial_texture_update_requests_
>= settings_
.max_partial_texture_updates
)
1051 partial_texture_update_requests_
++;
1055 void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor
) {
1056 if (device_scale_factor
== device_scale_factor_
)
1058 device_scale_factor_
= device_scale_factor
;
1063 void LayerTreeHost::UpdateTopControlsState(bool enable_hiding
,
1064 bool enable_showing
,
1066 if (!settings_
.calculate_top_controls_position
)
1069 proxy_
->ImplThread()->PostTask(
1070 base::Bind(&TopControlsManager::UpdateTopControlsState
,
1071 top_controls_manager_weak_ptr_
,
1077 bool LayerTreeHost::BlocksPendingCommit() const {
1080 return root_layer_
->BlocksPendingCommitRecursive();
1083 scoped_ptr
<base::Value
> LayerTreeHost::AsValue() const {
1084 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1085 state
->Set("proxy", proxy_
->AsValue().release());
1086 return state
.PassAs
<base::Value
>();
1089 void LayerTreeHost::AnimateLayers(base::TimeTicks time
) {
1090 if (!settings_
.accelerated_animation_enabled
||
1091 animation_registrar_
->active_animation_controllers().empty())
1094 TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers");
1096 double monotonic_time
= (time
- base::TimeTicks()).InSecondsF();
1098 AnimationRegistrar::AnimationControllerMap copy
=
1099 animation_registrar_
->active_animation_controllers();
1100 for (AnimationRegistrar::AnimationControllerMap::iterator iter
= copy
.begin();
1103 (*iter
).second
->Animate(monotonic_time
);
1104 bool start_ready_animations
= true;
1105 (*iter
).second
->UpdateState(start_ready_animations
, NULL
);
1109 skia::RefPtr
<SkPicture
> LayerTreeHost::CapturePicture() {
1110 return proxy_
->CapturePicture();