Move prefs::kLastPolicyStatisticsUpdate to the policy component.
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blob689cc452f082e6f9b8ecfac23d00949cbcfe4c21
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/single_thread_proxy.h"
7 #include "base/auto_reset.h"
8 #include "base/debug/trace_event.h"
9 #include "cc/output/context_provider.h"
10 #include "cc/output/output_surface.h"
11 #include "cc/quads/draw_quad.h"
12 #include "cc/resources/prioritized_resource_manager.h"
13 #include "cc/resources/resource_update_controller.h"
14 #include "cc/trees/blocking_task_runner.h"
15 #include "cc/trees/layer_tree_host.h"
16 #include "cc/trees/layer_tree_impl.h"
18 namespace cc {
20 scoped_ptr<Proxy> SingleThreadProxy::Create(LayerTreeHost* layer_tree_host) {
21 return make_scoped_ptr(
22 new SingleThreadProxy(layer_tree_host)).PassAs<Proxy>();
25 SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host)
26 : Proxy(NULL),
27 layer_tree_host_(layer_tree_host),
28 created_offscreen_context_provider_(false),
29 next_frame_is_newly_committed_frame_(false),
30 inside_draw_(false) {
31 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
32 DCHECK(Proxy::IsMainThread());
33 DCHECK(layer_tree_host);
35 // Impl-side painting not supported without threaded compositing.
36 CHECK(!layer_tree_host->settings().impl_side_painting)
37 << "Threaded compositing must be enabled to use impl-side painting.";
40 void SingleThreadProxy::Start(scoped_ptr<OutputSurface> first_output_surface) {
41 DCHECK(first_output_surface);
42 DebugScopedSetImplThread impl(this);
43 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
44 first_output_surface_ = first_output_surface.Pass();
47 SingleThreadProxy::~SingleThreadProxy() {
48 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
49 DCHECK(Proxy::IsMainThread());
50 // Make sure Stop() got called or never Started.
51 DCHECK(!layer_tree_host_impl_);
54 bool SingleThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
55 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeAndReadback");
56 DCHECK(Proxy::IsMainThread());
58 gfx::Rect device_viewport_damage_rect = rect;
60 LayerTreeHostImpl::FrameData frame;
61 if (!CommitAndComposite(base::TimeTicks::Now(),
62 device_viewport_damage_rect,
63 true, // for_readback
64 &frame))
65 return false;
68 DebugScopedSetImplThread impl(this);
69 layer_tree_host_impl_->Readback(pixels, rect);
71 if (layer_tree_host_impl_->IsContextLost())
72 return false;
75 return true;
78 void SingleThreadProxy::FinishAllRendering() {
79 DCHECK(Proxy::IsMainThread());
81 DebugScopedSetImplThread impl(this);
82 layer_tree_host_impl_->FinishAllRendering();
86 bool SingleThreadProxy::IsStarted() const {
87 DCHECK(Proxy::IsMainThread());
88 return layer_tree_host_impl_;
91 void SingleThreadProxy::SetLayerTreeHostClientReady() {
92 // Scheduling is controlled by the embedder in the single thread case, so
93 // nothing to do.
96 void SingleThreadProxy::SetVisible(bool visible) {
97 DebugScopedSetImplThread impl(this);
98 layer_tree_host_impl_->SetVisible(visible);
100 // Changing visibility could change ShouldComposite().
101 UpdateBackgroundAnimateTicking();
104 void SingleThreadProxy::CreateAndInitializeOutputSurface() {
105 TRACE_EVENT0(
106 "cc", "SingleThreadProxy::CreateAndInitializeOutputSurface");
107 DCHECK(Proxy::IsMainThread());
109 scoped_ptr<OutputSurface> output_surface = first_output_surface_.Pass();
110 if (!output_surface)
111 output_surface = layer_tree_host_->CreateOutputSurface();
112 if (!output_surface) {
113 OnOutputSurfaceInitializeAttempted(false);
114 return;
117 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
118 if (created_offscreen_context_provider_) {
119 offscreen_context_provider =
120 layer_tree_host_->client()->OffscreenContextProviderForMainThread();
121 if (!offscreen_context_provider.get()) {
122 OnOutputSurfaceInitializeAttempted(false);
123 return;
128 DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
129 DebugScopedSetImplThread impl(this);
130 layer_tree_host_->DeleteContentsTexturesOnImplThread(
131 layer_tree_host_impl_->resource_provider());
134 bool initialized;
136 DebugScopedSetImplThread impl(this);
138 DCHECK(output_surface);
139 initialized = layer_tree_host_impl_->InitializeRenderer(
140 output_surface.Pass());
141 if (initialized) {
142 renderer_capabilities_for_main_thread_ =
143 layer_tree_host_impl_->GetRendererCapabilities();
144 } else if (offscreen_context_provider.get()) {
145 offscreen_context_provider->VerifyContexts();
146 offscreen_context_provider = NULL;
149 layer_tree_host_impl_->SetOffscreenContextProvider(
150 offscreen_context_provider);
153 OnOutputSurfaceInitializeAttempted(initialized);
156 void SingleThreadProxy::OnOutputSurfaceInitializeAttempted(bool success) {
157 LayerTreeHost::CreateResult result =
158 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
159 if (result == LayerTreeHost::CreateFailedButTryAgain) {
160 // Force another recreation attempt to happen by requesting another commit.
161 SetNeedsCommit();
165 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
166 DCHECK(Proxy::IsMainThread());
167 DCHECK(!layer_tree_host_->output_surface_lost());
168 return renderer_capabilities_for_main_thread_;
171 void SingleThreadProxy::SetNeedsAnimate() {
172 // Thread-only feature.
173 NOTREACHED();
176 void SingleThreadProxy::SetNeedsUpdateLayers() {
177 DCHECK(Proxy::IsMainThread());
178 layer_tree_host_->ScheduleComposite();
181 void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
182 DCHECK(Proxy::IsMainThread());
183 // Commit immediately.
185 DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
186 DebugScopedSetImplThread impl(this);
188 // This CapturePostTasks should be destroyed before CommitComplete() is
189 // called since that goes out to the embedder, and we want the embedder
190 // to receive its callbacks before that.
191 BlockingTaskRunner::CapturePostTasks blocked;
193 RenderingStatsInstrumentation* stats_instrumentation =
194 layer_tree_host_->rendering_stats_instrumentation();
195 base::TimeTicks start_time = stats_instrumentation->StartRecording();
197 layer_tree_host_impl_->BeginCommit();
199 if (layer_tree_host_->contents_texture_manager()) {
200 layer_tree_host_->contents_texture_manager()->
201 PushTexturePrioritiesToBackings();
203 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
205 scoped_ptr<ResourceUpdateController> update_controller =
206 ResourceUpdateController::Create(
207 NULL,
208 Proxy::MainThreadTaskRunner(),
209 queue.Pass(),
210 layer_tree_host_impl_->resource_provider());
211 update_controller->Finalize();
213 if (layer_tree_host_impl_->EvictedUIResourcesExist())
214 layer_tree_host_->RecreateUIResources();
216 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
218 layer_tree_host_impl_->CommitComplete();
220 #ifndef NDEBUG
221 // In the single-threaded case, the scale and scroll deltas should never be
222 // touched on the impl layer tree.
223 scoped_ptr<ScrollAndScaleSet> scroll_info =
224 layer_tree_host_impl_->ProcessScrollDeltas();
225 DCHECK(!scroll_info->scrolls.size());
226 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
227 #endif
229 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
230 stats_instrumentation->AddCommit(duration);
231 stats_instrumentation->IssueTraceEventForMainThreadStats();
232 stats_instrumentation->AccumulateAndClearMainThreadStats();
234 layer_tree_host_->CommitComplete();
235 next_frame_is_newly_committed_frame_ = true;
238 void SingleThreadProxy::SetNeedsCommit() {
239 DCHECK(Proxy::IsMainThread());
240 layer_tree_host_->ScheduleComposite();
243 void SingleThreadProxy::SetNeedsRedraw(gfx::Rect damage_rect) {
244 SetNeedsRedrawRectOnImplThread(damage_rect);
247 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
248 // There is no activation here other than commit. So do nothing.
251 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
252 // Thread-only feature.
253 NOTREACHED();
256 bool SingleThreadProxy::CommitRequested() const { return false; }
258 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
259 return std::numeric_limits<size_t>::max();
262 void SingleThreadProxy::Stop() {
263 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
264 DCHECK(Proxy::IsMainThread());
266 DebugScopedSetMainThreadBlocked mainThreadBlocked(this);
267 DebugScopedSetImplThread impl(this);
269 layer_tree_host_->DeleteContentsTexturesOnImplThread(
270 layer_tree_host_impl_->resource_provider());
271 layer_tree_host_impl_.reset();
273 layer_tree_host_ = NULL;
276 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
277 DCHECK(Proxy::IsImplThread());
278 UpdateBackgroundAnimateTicking();
281 void SingleThreadProxy::NotifyReadyToActivate() {
282 // Thread-only feature.
283 NOTREACHED();
286 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
287 layer_tree_host_->ScheduleComposite();
290 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
291 // Thread-only/Impl-side-painting-only feature.
292 NOTREACHED();
295 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect) {
296 // TODO(brianderson): Once we move render_widget scheduling into this class,
297 // we can treat redraw requests more efficiently than CommitAndRedraw
298 // requests.
299 layer_tree_host_impl_->SetViewportDamage(damage_rect);
300 SetNeedsCommit();
303 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
304 // Impl-side painting only.
305 NOTREACHED();
308 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
309 layer_tree_host_->ScheduleComposite();
312 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
313 scoped_ptr<AnimationEventsVector> events,
314 base::Time wall_clock_time) {
315 DCHECK(Proxy::IsImplThread());
316 DebugScopedSetMainThread main(this);
317 layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
320 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
321 size_t limit_bytes,
322 int priority_cutoff) {
323 DCHECK(IsImplThread());
324 if (!layer_tree_host_->contents_texture_manager())
325 return false;
327 return layer_tree_host_->contents_texture_manager()->ReduceMemoryOnImplThread(
328 limit_bytes, priority_cutoff, layer_tree_host_impl_->resource_provider());
331 void SingleThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
332 // Impl-side painting only.
333 NOTREACHED();
336 void SingleThreadProxy::SendManagedMemoryStats() {
337 DCHECK(Proxy::IsImplThread());
338 if (!layer_tree_host_impl_)
339 return;
340 if (!layer_tree_host_->contents_texture_manager())
341 return;
343 PrioritizedResourceManager* contents_texture_manager =
344 layer_tree_host_->contents_texture_manager();
345 layer_tree_host_impl_->SendManagedMemoryStats(
346 contents_texture_manager->MemoryVisibleBytes(),
347 contents_texture_manager->MemoryVisibleAndNearbyBytes(),
348 contents_texture_manager->MemoryUseBytes());
351 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
353 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
354 // Cause a commit so we can notice the lost context.
355 SetNeedsCommitOnImplThread();
358 // Called by the legacy scheduling path (e.g. where render_widget does the
359 // scheduling)
360 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
361 gfx::Rect device_viewport_damage_rect;
363 LayerTreeHostImpl::FrameData frame;
364 if (CommitAndComposite(frame_begin_time,
365 device_viewport_damage_rect,
366 false, // for_readback
367 &frame)) {
368 layer_tree_host_impl_->SwapBuffers(frame);
369 DidSwapFrame();
373 scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
374 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
376 // The following line casts away const modifiers because it is just
377 // setting debug state. We still want the AsValue() function and its
378 // call chain to be const throughout.
379 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
381 state->Set("layer_tree_host_impl",
382 layer_tree_host_impl_->AsValue().release());
384 return state.PassAs<base::Value>();
387 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
389 DebugScopedSetImplThread impl(this);
390 if (layer_tree_host_impl_->renderer()) {
391 DCHECK(!layer_tree_host_->output_surface_lost());
392 layer_tree_host_impl_->renderer()->DoNoOp();
397 bool SingleThreadProxy::CommitAndComposite(
398 base::TimeTicks frame_begin_time,
399 gfx::Rect device_viewport_damage_rect,
400 bool for_readback,
401 LayerTreeHostImpl::FrameData* frame) {
402 DCHECK(Proxy::IsMainThread());
404 if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded())
405 return false;
407 layer_tree_host_->AnimateLayers(frame_begin_time);
409 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
410 if (renderer_capabilities_for_main_thread_.using_offscreen_context3d &&
411 layer_tree_host_->needs_offscreen_context()) {
412 offscreen_context_provider =
413 layer_tree_host_->client()->OffscreenContextProviderForMainThread();
414 if (offscreen_context_provider.get())
415 created_offscreen_context_provider_ = true;
418 if (layer_tree_host_->contents_texture_manager()) {
419 layer_tree_host_->contents_texture_manager()
420 ->UnlinkAndClearEvictedBackings();
423 scoped_ptr<ResourceUpdateQueue> queue =
424 make_scoped_ptr(new ResourceUpdateQueue);
425 layer_tree_host_->UpdateLayers(
426 queue.get(), layer_tree_host_impl_->memory_allocation_limit_bytes());
428 layer_tree_host_->WillCommit();
429 DoCommit(queue.Pass());
430 bool result = DoComposite(offscreen_context_provider,
431 frame_begin_time,
432 device_viewport_damage_rect,
433 for_readback,
434 frame);
435 layer_tree_host_->DidBeginFrame();
436 return result;
439 bool SingleThreadProxy::ShouldComposite() const {
440 DCHECK(Proxy::IsImplThread());
441 return layer_tree_host_impl_->visible() &&
442 layer_tree_host_impl_->CanDraw();
445 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
446 DCHECK(Proxy::IsImplThread());
447 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
448 !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
451 bool SingleThreadProxy::DoComposite(
452 scoped_refptr<cc::ContextProvider> offscreen_context_provider,
453 base::TimeTicks frame_begin_time,
454 gfx::Rect device_viewport_damage_rect,
455 bool for_readback,
456 LayerTreeHostImpl::FrameData* frame) {
457 DCHECK(!layer_tree_host_->output_surface_lost());
459 bool lost_output_surface = false;
461 DebugScopedSetImplThread impl(this);
462 base::AutoReset<bool> mark_inside(&inside_draw_, true);
464 layer_tree_host_impl_->SetOffscreenContextProvider(
465 offscreen_context_provider);
467 bool can_do_readback = layer_tree_host_impl_->renderer()->CanReadPixels();
469 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
470 // frame, so can only be used when such a frame is possible. Since
471 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
472 // CanDraw() as well.
473 if (!ShouldComposite() || (for_readback && !can_do_readback)) {
474 UpdateBackgroundAnimateTicking();
475 return false;
478 layer_tree_host_impl_->Animate(
479 layer_tree_host_impl_->CurrentFrameTimeTicks(),
480 layer_tree_host_impl_->CurrentFrameTime());
481 UpdateBackgroundAnimateTicking();
483 layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
484 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
485 layer_tree_host_impl_->DidDrawAllLayers(*frame);
486 lost_output_surface = layer_tree_host_impl_->IsContextLost();
488 bool start_ready_animations = true;
489 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
491 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
494 if (lost_output_surface) {
495 cc::ContextProvider* offscreen_contexts =
496 layer_tree_host_impl_->offscreen_context_provider();
497 if (offscreen_contexts)
498 offscreen_contexts->VerifyContexts();
499 layer_tree_host_->DidLoseOutputSurface();
500 return false;
503 return true;
506 void SingleThreadProxy::DidSwapFrame() {
507 if (next_frame_is_newly_committed_frame_) {
508 next_frame_is_newly_committed_frame_ = false;
509 layer_tree_host_->DidCommitAndDrawFrame();
513 bool SingleThreadProxy::CommitPendingForTesting() { return false; }
515 } // namespace cc