Getting rid of GetDefaultProfile(), clean up of ProfileManager (which was in a seriou...
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
blob8bdd7653d57fef3cb77cc408de3a1e3f4ee82bff
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/debug/benchmark_instrumentation.h"
10 #include "cc/output/context_provider.h"
11 #include "cc/output/output_surface.h"
12 #include "cc/quads/draw_quad.h"
13 #include "cc/resources/prioritized_resource_manager.h"
14 #include "cc/resources/resource_update_controller.h"
15 #include "cc/trees/blocking_task_runner.h"
16 #include "cc/trees/layer_tree_host.h"
17 #include "cc/trees/layer_tree_host_single_thread_client.h"
18 #include "cc/trees/layer_tree_impl.h"
19 #include "ui/gfx/frame_time.h"
21 namespace cc {
23 scoped_ptr<Proxy> SingleThreadProxy::Create(
24 LayerTreeHost* layer_tree_host,
25 LayerTreeHostSingleThreadClient* client) {
26 return make_scoped_ptr(
27 new SingleThreadProxy(layer_tree_host, client)).PassAs<Proxy>();
30 SingleThreadProxy::SingleThreadProxy(LayerTreeHost* layer_tree_host,
31 LayerTreeHostSingleThreadClient* client)
32 : Proxy(NULL),
33 layer_tree_host_(layer_tree_host),
34 client_(client),
35 created_offscreen_context_provider_(false),
36 next_frame_is_newly_committed_frame_(false),
37 inside_draw_(false) {
38 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
39 DCHECK(Proxy::IsMainThread());
40 DCHECK(layer_tree_host);
42 // Impl-side painting not supported without threaded compositing.
43 CHECK(!layer_tree_host->settings().impl_side_painting)
44 << "Threaded compositing must be enabled to use impl-side painting.";
47 void SingleThreadProxy::Start() {
48 DebugScopedSetImplThread impl(this);
49 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
52 SingleThreadProxy::~SingleThreadProxy() {
53 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
54 DCHECK(Proxy::IsMainThread());
55 // Make sure Stop() got called or never Started.
56 DCHECK(!layer_tree_host_impl_);
59 bool SingleThreadProxy::CompositeAndReadback(void* pixels,
60 const gfx::Rect& rect) {
61 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeAndReadback");
62 DCHECK(Proxy::IsMainThread());
64 gfx::Rect device_viewport_damage_rect = rect;
66 LayerTreeHostImpl::FrameData frame;
67 if (!CommitAndComposite(gfx::FrameTime::Now(),
68 device_viewport_damage_rect,
69 true, // for_readback
70 &frame))
71 return false;
74 DebugScopedSetImplThread impl(this);
75 layer_tree_host_impl_->Readback(pixels, rect);
77 if (layer_tree_host_impl_->IsContextLost())
78 return false;
81 return true;
84 void SingleThreadProxy::FinishAllRendering() {
85 DCHECK(Proxy::IsMainThread());
87 DebugScopedSetImplThread impl(this);
88 layer_tree_host_impl_->FinishAllRendering();
92 bool SingleThreadProxy::IsStarted() const {
93 DCHECK(Proxy::IsMainThread());
94 return layer_tree_host_impl_;
97 void SingleThreadProxy::SetLayerTreeHostClientReady() {
98 // Scheduling is controlled by the embedder in the single thread case, so
99 // nothing to do.
102 void SingleThreadProxy::SetVisible(bool visible) {
103 DebugScopedSetImplThread impl(this);
104 layer_tree_host_impl_->SetVisible(visible);
106 // Changing visibility could change ShouldComposite().
107 UpdateBackgroundAnimateTicking();
110 void SingleThreadProxy::CreateAndInitializeOutputSurface() {
111 TRACE_EVENT0(
112 "cc", "SingleThreadProxy::CreateAndInitializeOutputSurface");
113 DCHECK(Proxy::IsMainThread());
115 scoped_ptr<OutputSurface> output_surface =
116 layer_tree_host_->CreateOutputSurface();
117 if (!output_surface) {
118 OnOutputSurfaceInitializeAttempted(false);
119 return;
122 scoped_refptr<ContextProvider> offscreen_context_provider;
123 if (created_offscreen_context_provider_) {
124 offscreen_context_provider =
125 layer_tree_host_->client()->OffscreenContextProvider();
126 if (!offscreen_context_provider.get() ||
127 !offscreen_context_provider->BindToCurrentThread()) {
128 OnOutputSurfaceInitializeAttempted(false);
129 return;
134 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
135 DebugScopedSetImplThread impl(this);
136 layer_tree_host_->DeleteContentsTexturesOnImplThread(
137 layer_tree_host_impl_->resource_provider());
140 bool initialized;
142 DebugScopedSetImplThread impl(this);
144 DCHECK(output_surface);
145 initialized = layer_tree_host_impl_->InitializeRenderer(
146 output_surface.Pass());
147 if (initialized) {
148 renderer_capabilities_for_main_thread_ =
149 layer_tree_host_impl_->GetRendererCapabilities();
150 } else if (offscreen_context_provider.get()) {
151 offscreen_context_provider->VerifyContexts();
152 offscreen_context_provider = NULL;
155 layer_tree_host_impl_->SetOffscreenContextProvider(
156 offscreen_context_provider);
159 OnOutputSurfaceInitializeAttempted(initialized);
162 void SingleThreadProxy::OnOutputSurfaceInitializeAttempted(bool success) {
163 LayerTreeHost::CreateResult result =
164 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
165 if (result == LayerTreeHost::CreateFailedButTryAgain) {
166 // Force another recreation attempt to happen by requesting another commit.
167 SetNeedsCommit();
171 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
172 DCHECK(Proxy::IsMainThread());
173 DCHECK(!layer_tree_host_->output_surface_lost());
174 return renderer_capabilities_for_main_thread_;
177 void SingleThreadProxy::SetNeedsAnimate() {
178 DCHECK(Proxy::IsMainThread());
179 client_->ScheduleAnimation();
182 void SingleThreadProxy::SetNeedsUpdateLayers() {
183 DCHECK(Proxy::IsMainThread());
184 client_->ScheduleComposite();
187 void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
188 DCHECK(Proxy::IsMainThread());
189 // Commit immediately.
191 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
192 DebugScopedSetImplThread impl(this);
194 // This CapturePostTasks should be destroyed before CommitComplete() is
195 // called since that goes out to the embedder, and we want the embedder
196 // to receive its callbacks before that.
197 BlockingTaskRunner::CapturePostTasks blocked;
199 layer_tree_host_impl_->BeginCommit();
201 if (PrioritizedResourceManager* contents_texture_manager =
202 layer_tree_host_->contents_texture_manager()) {
203 contents_texture_manager->PushTexturePrioritiesToBackings();
205 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
207 scoped_ptr<ResourceUpdateController> update_controller =
208 ResourceUpdateController::Create(
209 NULL,
210 Proxy::MainThreadTaskRunner(),
211 queue.Pass(),
212 layer_tree_host_impl_->resource_provider());
213 update_controller->Finalize();
215 if (layer_tree_host_impl_->EvictedUIResourcesExist())
216 layer_tree_host_->RecreateUIResources();
218 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
220 layer_tree_host_impl_->CommitComplete();
222 #ifndef NDEBUG
223 // In the single-threaded case, the scale and scroll deltas should never be
224 // touched on the impl layer tree.
225 scoped_ptr<ScrollAndScaleSet> scroll_info =
226 layer_tree_host_impl_->ProcessScrollDeltas();
227 DCHECK(!scroll_info->scrolls.size());
228 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
229 #endif
231 RenderingStatsInstrumentation* stats_instrumentation =
232 layer_tree_host_->rendering_stats_instrumentation();
233 BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
234 stats_instrumentation->main_thread_rendering_stats());
235 stats_instrumentation->AccumulateAndClearMainThreadStats();
237 layer_tree_host_->CommitComplete();
238 next_frame_is_newly_committed_frame_ = true;
241 void SingleThreadProxy::SetNeedsCommit() {
242 DCHECK(Proxy::IsMainThread());
243 client_->ScheduleComposite();
246 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
247 SetNeedsRedrawRectOnImplThread(damage_rect);
248 client_->ScheduleComposite();
251 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
252 // There is no activation here other than commit. So do nothing.
255 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
256 // Thread-only feature.
257 NOTREACHED();
260 bool SingleThreadProxy::CommitRequested() const { return false; }
262 bool SingleThreadProxy::BeginMainFrameRequested() const { return false; }
264 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
265 return std::numeric_limits<size_t>::max();
268 void SingleThreadProxy::Stop() {
269 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
270 DCHECK(Proxy::IsMainThread());
272 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
273 DebugScopedSetImplThread impl(this);
275 layer_tree_host_->DeleteContentsTexturesOnImplThread(
276 layer_tree_host_impl_->resource_provider());
277 layer_tree_host_impl_.reset();
279 layer_tree_host_ = NULL;
282 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
283 DCHECK(Proxy::IsImplThread());
284 UpdateBackgroundAnimateTicking();
287 void SingleThreadProxy::NotifyReadyToActivate() {
288 // Thread-only feature.
289 NOTREACHED();
292 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
293 client_->ScheduleComposite();
296 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
297 // Thread-only/Impl-side-painting-only feature.
298 NOTREACHED();
301 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
302 const gfx::Rect& damage_rect) {
303 // TODO(brianderson): Once we move render_widget scheduling into this class,
304 // we can treat redraw requests more efficiently than CommitAndRedraw
305 // requests.
306 layer_tree_host_impl_->SetViewportDamage(damage_rect);
307 SetNeedsCommit();
310 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
311 // Impl-side painting only.
312 NOTREACHED();
315 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
316 client_->ScheduleComposite();
319 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
320 scoped_ptr<AnimationEventsVector> events,
321 base::Time wall_clock_time) {
322 DCHECK(Proxy::IsImplThread());
323 DebugScopedSetMainThread main(this);
324 layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
327 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
328 size_t limit_bytes,
329 int priority_cutoff) {
330 DCHECK(IsImplThread());
331 PrioritizedResourceManager* contents_texture_manager =
332 layer_tree_host_->contents_texture_manager();
334 ResourceProvider* resource_provider =
335 layer_tree_host_impl_->resource_provider();
337 if (!contents_texture_manager || !resource_provider)
338 return false;
340 return contents_texture_manager->ReduceMemoryOnImplThread(
341 limit_bytes, priority_cutoff, resource_provider);
344 void SingleThreadProxy::SendManagedMemoryStats() {
345 DCHECK(Proxy::IsImplThread());
346 if (!layer_tree_host_impl_)
347 return;
348 PrioritizedResourceManager* contents_texture_manager =
349 layer_tree_host_->contents_texture_manager();
350 if (!contents_texture_manager)
351 return;
353 layer_tree_host_impl_->SendManagedMemoryStats(
354 contents_texture_manager->MemoryVisibleBytes(),
355 contents_texture_manager->MemoryVisibleAndNearbyBytes(),
356 contents_texture_manager->MemoryUseBytes());
359 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
361 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
362 // Cause a commit so we can notice the lost context.
363 SetNeedsCommitOnImplThread();
364 client_->DidAbortSwapBuffers();
367 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
368 client_->DidPostSwapBuffers();
371 void SingleThreadProxy::OnSwapBuffersCompleteOnImplThread() {
372 client_->DidCompleteSwapBuffers();
375 // Called by the legacy scheduling path (e.g. where render_widget does the
376 // scheduling)
377 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
378 gfx::Rect device_viewport_damage_rect;
380 LayerTreeHostImpl::FrameData frame;
381 if (CommitAndComposite(frame_begin_time,
382 device_viewport_damage_rect,
383 false, // for_readback
384 &frame)) {
386 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
387 DebugScopedSetImplThread impl(this);
389 // This CapturePostTasks should be destroyed before
390 // DidCommitAndDrawFrame() is called since that goes out to the embedder,
391 // and we want the embedder to receive its callbacks before that.
392 // NOTE: This maintains consistent ordering with the ThreadProxy since
393 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
394 // there as the main thread is not blocked, so any posted tasks inside
395 // the swap buffers will execute first.
396 BlockingTaskRunner::CapturePostTasks blocked;
398 layer_tree_host_impl_->SwapBuffers(frame);
400 DidSwapFrame();
404 scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
405 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
407 // The following line casts away const modifiers because it is just
408 // setting debug state. We still want the AsValue() function and its
409 // call chain to be const throughout.
410 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
412 state->Set("layer_tree_host_impl",
413 layer_tree_host_impl_->AsValue().release());
415 return state.PassAs<base::Value>();
418 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
420 DebugScopedSetImplThread impl(this);
421 if (layer_tree_host_impl_->renderer()) {
422 DCHECK(!layer_tree_host_->output_surface_lost());
423 layer_tree_host_impl_->renderer()->DoNoOp();
428 bool SingleThreadProxy::CommitAndComposite(
429 base::TimeTicks frame_begin_time,
430 const gfx::Rect& device_viewport_damage_rect,
431 bool for_readback,
432 LayerTreeHostImpl::FrameData* frame) {
433 DCHECK(Proxy::IsMainThread());
435 if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded())
436 return false;
438 layer_tree_host_->AnimateLayers(frame_begin_time);
440 if (PrioritizedResourceManager* contents_texture_manager =
441 layer_tree_host_->contents_texture_manager()) {
442 contents_texture_manager->UnlinkAndClearEvictedBackings();
443 contents_texture_manager->SetMaxMemoryLimitBytes(
444 layer_tree_host_impl_->memory_allocation_limit_bytes());
445 contents_texture_manager->SetExternalPriorityCutoff(
446 layer_tree_host_impl_->memory_allocation_priority_cutoff());
449 scoped_ptr<ResourceUpdateQueue> queue =
450 make_scoped_ptr(new ResourceUpdateQueue);
451 layer_tree_host_->UpdateLayers(queue.get());
453 layer_tree_host_->WillCommit();
455 scoped_refptr<ContextProvider> offscreen_context_provider;
456 if (renderer_capabilities_for_main_thread_.using_offscreen_context3d &&
457 layer_tree_host_->needs_offscreen_context()) {
458 offscreen_context_provider =
459 layer_tree_host_->client()->OffscreenContextProvider();
460 if (offscreen_context_provider.get() &&
461 !offscreen_context_provider->BindToCurrentThread())
462 offscreen_context_provider = NULL;
464 if (offscreen_context_provider.get())
465 created_offscreen_context_provider_ = true;
468 DoCommit(queue.Pass());
469 bool result = DoComposite(offscreen_context_provider,
470 frame_begin_time,
471 device_viewport_damage_rect,
472 for_readback,
473 frame);
474 layer_tree_host_->DidBeginMainFrame();
475 return result;
478 bool SingleThreadProxy::ShouldComposite() const {
479 DCHECK(Proxy::IsImplThread());
480 return layer_tree_host_impl_->visible() &&
481 layer_tree_host_impl_->CanDraw();
484 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
485 DCHECK(Proxy::IsImplThread());
486 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
487 !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
490 bool SingleThreadProxy::DoComposite(
491 scoped_refptr<ContextProvider> offscreen_context_provider,
492 base::TimeTicks frame_begin_time,
493 const gfx::Rect& device_viewport_damage_rect,
494 bool for_readback,
495 LayerTreeHostImpl::FrameData* frame) {
496 DCHECK(!layer_tree_host_->output_surface_lost());
498 bool lost_output_surface = false;
500 DebugScopedSetImplThread impl(this);
501 base::AutoReset<bool> mark_inside(&inside_draw_, true);
503 layer_tree_host_impl_->SetOffscreenContextProvider(
504 offscreen_context_provider);
506 bool can_do_readback = layer_tree_host_impl_->renderer()->CanReadPixels();
508 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
509 // frame, so can only be used when such a frame is possible. Since
510 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
511 // CanDraw() as well.
512 if (!ShouldComposite() || (for_readback && !can_do_readback)) {
513 UpdateBackgroundAnimateTicking();
514 return false;
517 layer_tree_host_impl_->Animate(
518 layer_tree_host_impl_->CurrentFrameTimeTicks(),
519 layer_tree_host_impl_->CurrentFrameTime());
520 UpdateBackgroundAnimateTicking();
522 if (!layer_tree_host_impl_->IsContextLost()) {
523 layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
524 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
525 layer_tree_host_impl_->DidDrawAllLayers(*frame);
527 lost_output_surface = layer_tree_host_impl_->IsContextLost();
529 bool start_ready_animations = true;
530 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
532 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
535 if (lost_output_surface) {
536 ContextProvider* offscreen_contexts =
537 layer_tree_host_impl_->offscreen_context_provider();
538 if (offscreen_contexts)
539 offscreen_contexts->VerifyContexts();
540 layer_tree_host_->DidLoseOutputSurface();
541 return false;
544 return true;
547 void SingleThreadProxy::DidSwapFrame() {
548 if (next_frame_is_newly_committed_frame_) {
549 next_frame_is_newly_committed_frame_ = false;
550 layer_tree_host_->DidCommitAndDrawFrame();
554 bool SingleThreadProxy::CommitPendingForTesting() { return false; }
556 } // namespace cc