Add signalSyncPoint to the WebGraphicsContext3D command buffer impls.
[chromium-blink-merge.git] / cc / trees / layer_tree_host.cc
blobbed4e8687ad699f9f29dbd6ab0a2a83efe488ed4
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"
7 #include <algorithm>
8 #include <stack>
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"
43 namespace {
44 static int s_num_layer_tree_instances;
47 namespace cc {
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),
59 max_texture_size(0),
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,
73 settings));
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)
81 : animating_(false),
82 needs_full_tree_sync_(true),
83 needs_filter_context_(false),
84 client_(client),
85 commit_number_(0),
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),
91 settings_(settings),
92 debug_state_(settings.initial_debug_state),
93 overdraw_bottom_height_(0.f),
94 device_scale_factor_(1.f),
95 visible_(true),
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) {
113 if (impl_thread)
114 return InitializeProxy(ThreadProxy::Create(this, impl_thread.Pass()));
115 else
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();
127 proxy_->Start();
128 return proxy_->InitializeOutputSurface();
131 LayerTreeHost::~LayerTreeHost() {
132 if (root_layer_)
133 root_layer_->SetLayerTreeHost(NULL);
134 DCHECK(proxy_);
135 DCHECK(proxy_->IsMainThread());
136 TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
137 proxy_->Stop();
138 s_num_layer_tree_instances--;
139 RateLimiterMap::iterator it = rate_limiters_.begin();
140 if (it != rate_limiters_.end())
141 it->second->Stop();
143 if (root_layer_) {
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.
147 root_layer_ = NULL;
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
159 // surface.
160 renderer_can_be_initialized_ = false;
161 client_->DidRecreateOutputSurface(false);
162 return;
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
204 // another commit.
205 if (!proxy_->HasImplThread())
206 SetNeedsCommit();
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) {
234 animating_ = true;
235 client_->Animate((frame_begin_time - base::TimeTicks()).InSecondsF());
236 AnimateLayers(frame_begin_time);
237 animating_ = false;
239 rendering_stats_instrumentation_->IncrementAnimationFrameCount();
242 void LayerTreeHost::DidStopFlinging() {
243 proxy_->MainThreadHasStoppedFlinging();
246 void LayerTreeHost::Layout() {
247 client_->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();
294 } else {
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));
314 } else {
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();
332 } else {
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();
380 commit_number_++;
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()));
387 gfx::Size size;
388 int track_width = PinchZoomScrollbarGeometry::kTrackWidth;
389 if (orientation == WebKit::WebScrollbar::Horizontal)
390 size = gfx::Size(viewport_size.width() - track_width, track_width);
391 else
392 size = gfx::Size(track_width, viewport_size.height() - track_width);
393 return size;
396 void LayerTreeHost::SetPinchZoomScrollbarsBoundsAndPosition() {
397 if (!pinch_zoom_scrollbar_horizontal_ || !pinch_zoom_scrollbar_vertical_)
398 return;
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()) {
460 if (!hud_layer_)
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();
467 hud_layer_ = NULL;
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_,
488 client,
489 proxy_.get(),
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;
504 SetNeedsCommit();
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;
512 return ret;
515 void LayerTreeHost::FinishAllRendering() {
516 if (!renderer_initialized_)
517 return;
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();
532 layer_stack.pop();
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;
566 SetNeedsCommit();
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());
600 break;
602 case AnimationEvent::Finished:
603 (*iter).second->NotifyAnimationFinished((*events)[event_index],
604 wall_clock_time.ToDoubleT());
605 break;
607 case AnimationEvent::PropertyUpdate:
608 (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
609 break;
611 default:
612 NOTREACHED();
618 void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
619 if (root_layer_ == root_layer)
620 return;
622 if (root_layer_)
623 root_layer_->SetLayerTreeHost(NULL);
624 root_layer_ = root_layer;
625 if (root_layer_)
626 root_layer_->SetLayerTreeHost(this);
628 if (hud_layer_)
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))
645 return;
647 debug_state_ = new_debug_state;
649 rendering_stats_instrumentation_->set_record_rendering_stats(
650 debug_state_.RecordRenderingStats());
652 SetNeedsCommit();
655 void LayerTreeHost::SetViewportSize(gfx::Size device_viewport_size) {
656 if (device_viewport_size == device_viewport_size_)
657 return;
659 device_viewport_size_ = device_viewport_size;
661 SetPinchZoomScrollbarsBoundsAndPosition();
662 SetNeedsCommit();
665 void LayerTreeHost::SetOverdrawBottomHeight(float overdraw_bottom_height) {
666 if (overdraw_bottom_height_ == overdraw_bottom_height)
667 return;
669 overdraw_bottom_height_ = overdraw_bottom_height;
670 SetNeedsCommit();
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_)
679 return;
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;
684 SetNeedsCommit();
687 void LayerTreeHost::SetVisible(bool visible) {
688 if (visible_ == visible)
689 return;
690 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,
699 bool use_anchor,
700 float scale,
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;
708 SetNeedsCommit();
711 void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
712 if (!proxy_->HasImplThread())
713 static_cast<SingleThreadProxy*>(proxy_.get())->CompositeImmediately(
714 frame_begin_time);
715 else
716 SetNeedsCommit();
719 void LayerTreeHost::ScheduleComposite() {
720 client_->ScheduleComposite();
723 bool LayerTreeHost::InitializeRendererIfNeeded() {
724 if (!renderer_can_be_initialized_)
725 return false;
727 if (!renderer_initialized_) {
728 InitializeRenderer();
729 // If we couldn't initialize, then bail since we're returning to software
730 // mode.
731 if (!renderer_initialized_)
732 return false;
734 if (output_surface_lost_) {
735 if (RecreateOutputSurface() != RecreateSucceeded)
736 return false;
738 return true;
741 void LayerTreeHost::UpdateLayers(ResourceUpdateQueue* queue,
742 size_t memory_allocation_limit_bytes) {
743 DCHECK(renderer_initialized_);
745 if (!root_layer())
746 return;
748 if (device_viewport_size().IsEmpty())
749 return;
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) {
760 if (!layer)
761 return NULL;
763 if (layer->scrollable())
764 return layer;
766 for (size_t i = 0; i < layer->children().size(); ++i) {
767 Layer* found = FindFirstScrollableLayer(layer->children()[i].get());
768 if (found)
769 return found;
772 return NULL;
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;
785 UpdateHudLayer();
787 Layer* root_scroll = FindFirstScrollableLayer(root_layer);
789 TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
790 LayerTreeHostCommon::CalculateDrawProperties(
791 root_layer,
792 device_viewport_size(),
793 device_scale_factor_,
794 page_scale_factor_,
795 root_scroll,
796 GetRendererCapabilities().max_texture_size,
797 settings_.can_use_lcd_text,
798 &update_list);
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(),
813 prepaint_delay);
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");
823 SetNeedsCommit();
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,
840 LayerList,
841 RenderSurface,
842 LayerIteratorActions::BackToFront> LayerIteratorType;
844 PriorityCalculator calculator;
845 LayerIteratorType end = LayerIteratorType::End(&update_list);
846 for (LayerIteratorType it = LayerIteratorType::Begin(&update_list);
847 it != end;
848 ++it) {
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
885 // cost.
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();
890 size_t bytes =
891 Resource::MemorySizeBytes(render_surface->content_rect().size(),
892 GL_RGBA);
893 contents_texture_bytes += bytes;
895 if (render_surface_layer->background_filters().isEmpty())
896 continue;
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_,
902 GL_RGBA);
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
914 // painted.
916 bool need_more_updates = false;
917 Layer* mask_layer = render_surface_layer->mask_layer();
918 if (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,
938 LayerList,
939 RenderSurface,
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);
965 it != end;
966 ++it) {
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) {
994 if (!root_layer_)
995 return;
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) {
1001 Layer* layer =
1002 LayerTreeHostCommon::FindLayerInSubtree(root_layer_.get(),
1003 info.scrolls[i].layer_id);
1004 if (!layer)
1005 continue;
1006 if (layer == root_scroll_layer)
1007 root_scroll_delta += info.scrolls[i].scroll_delta;
1008 else
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) {
1017 if (animating_)
1018 return;
1020 DCHECK(context3d);
1021 RateLimiterMap::iterator it = rate_limiters_.find(context3d);
1022 if (it != rate_limiters_.end()) {
1023 it->second->Start();
1024 } else {
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()) {
1035 it->second->Stop();
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
1043 // SwapBuffers.
1044 proxy_->ForceSerializeOnSwapBuffers();
1047 bool LayerTreeHost::RequestPartialTextureUpdate() {
1048 if (partial_texture_update_requests_ >= settings_.max_partial_texture_updates)
1049 return false;
1051 partial_texture_update_requests_++;
1052 return true;
1055 void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) {
1056 if (device_scale_factor == device_scale_factor_)
1057 return;
1058 device_scale_factor_ = device_scale_factor;
1060 SetNeedsCommit();
1063 void LayerTreeHost::UpdateTopControlsState(bool enable_hiding,
1064 bool enable_showing,
1065 bool animate) {
1066 if (!settings_.calculate_top_controls_position)
1067 return;
1069 proxy_->ImplThread()->PostTask(
1070 base::Bind(&TopControlsManager::UpdateTopControlsState,
1071 top_controls_manager_weak_ptr_,
1072 enable_hiding,
1073 enable_showing,
1074 animate));
1077 bool LayerTreeHost::BlocksPendingCommit() const {
1078 if (!root_layer_)
1079 return false;
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())
1092 return;
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();
1101 iter != copy.end();
1102 ++iter) {
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();
1113 } // namespace cc