Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / cc / trees / single_thread_proxy.cc
bloba920f5a28ac25e3425de7d50ff0f7ca0df5fffe1
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 next_frame_is_newly_committed_frame_(false),
36 inside_draw_(false) {
37 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
38 DCHECK(Proxy::IsMainThread());
39 DCHECK(layer_tree_host);
41 // Impl-side painting not supported without threaded compositing.
42 CHECK(!layer_tree_host->settings().impl_side_painting)
43 << "Threaded compositing must be enabled to use impl-side painting.";
46 void SingleThreadProxy::Start() {
47 DebugScopedSetImplThread impl(this);
48 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
51 SingleThreadProxy::~SingleThreadProxy() {
52 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
53 DCHECK(Proxy::IsMainThread());
54 // Make sure Stop() got called or never Started.
55 DCHECK(!layer_tree_host_impl_);
58 bool SingleThreadProxy::CompositeAndReadback(void* pixels,
59 const gfx::Rect& rect) {
60 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeAndReadback");
61 DCHECK(Proxy::IsMainThread());
63 gfx::Rect device_viewport_damage_rect = rect;
65 LayerTreeHostImpl::FrameData frame;
66 if (!CommitAndComposite(gfx::FrameTime::Now(),
67 device_viewport_damage_rect,
68 true, // for_readback
69 &frame))
70 return false;
73 DebugScopedSetImplThread impl(this);
74 layer_tree_host_impl_->Readback(pixels, rect);
76 if (layer_tree_host_impl_->IsContextLost())
77 return false;
80 return true;
83 void SingleThreadProxy::FinishAllRendering() {
84 TRACE_EVENT0("cc", "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 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
99 // Scheduling is controlled by the embedder in the single thread case, so
100 // nothing to do.
103 void SingleThreadProxy::SetVisible(bool visible) {
104 TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
105 DebugScopedSetImplThread impl(this);
106 layer_tree_host_impl_->SetVisible(visible);
108 // Changing visibility could change ShouldComposite().
109 UpdateBackgroundAnimateTicking();
112 void SingleThreadProxy::CreateAndInitializeOutputSurface() {
113 TRACE_EVENT0(
114 "cc", "SingleThreadProxy::CreateAndInitializeOutputSurface");
115 DCHECK(Proxy::IsMainThread());
117 scoped_ptr<OutputSurface> output_surface =
118 layer_tree_host_->CreateOutputSurface();
120 renderer_capabilities_for_main_thread_ = RendererCapabilities();
122 bool success = !!output_surface;
123 if (success) {
124 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
125 DebugScopedSetImplThread impl(this);
126 layer_tree_host_->DeleteContentsTexturesOnImplThread(
127 layer_tree_host_impl_->resource_provider());
128 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
131 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
133 if (!success) {
134 // Force another recreation attempt to happen by requesting another commit.
135 SetNeedsCommit();
139 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
140 DCHECK(Proxy::IsMainThread());
141 DCHECK(!layer_tree_host_->output_surface_lost());
142 return renderer_capabilities_for_main_thread_;
145 void SingleThreadProxy::SetNeedsAnimate() {
146 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
147 DCHECK(Proxy::IsMainThread());
148 client_->ScheduleAnimation();
151 void SingleThreadProxy::SetNeedsUpdateLayers() {
152 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
153 DCHECK(Proxy::IsMainThread());
154 client_->ScheduleComposite();
157 void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
158 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
159 DCHECK(Proxy::IsMainThread());
160 // Commit immediately.
162 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
163 DebugScopedSetImplThread impl(this);
165 // This CapturePostTasks should be destroyed before CommitComplete() is
166 // called since that goes out to the embedder, and we want the embedder
167 // to receive its callbacks before that.
168 BlockingTaskRunner::CapturePostTasks blocked;
170 layer_tree_host_impl_->BeginCommit();
172 if (PrioritizedResourceManager* contents_texture_manager =
173 layer_tree_host_->contents_texture_manager()) {
174 contents_texture_manager->PushTexturePrioritiesToBackings();
176 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
178 scoped_ptr<ResourceUpdateController> update_controller =
179 ResourceUpdateController::Create(
180 NULL,
181 Proxy::MainThreadTaskRunner(),
182 queue.Pass(),
183 layer_tree_host_impl_->resource_provider());
184 update_controller->Finalize();
186 if (layer_tree_host_impl_->EvictedUIResourcesExist())
187 layer_tree_host_->RecreateUIResources();
189 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
191 layer_tree_host_impl_->CommitComplete();
193 #if DCHECK_IS_ON
194 // In the single-threaded case, the scale and scroll deltas should never be
195 // touched on the impl layer tree.
196 scoped_ptr<ScrollAndScaleSet> scroll_info =
197 layer_tree_host_impl_->ProcessScrollDeltas();
198 DCHECK(!scroll_info->scrolls.size());
199 DCHECK_EQ(1.f, scroll_info->page_scale_delta);
200 #endif
202 RenderingStatsInstrumentation* stats_instrumentation =
203 layer_tree_host_->rendering_stats_instrumentation();
204 BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
205 stats_instrumentation->main_thread_rendering_stats());
206 stats_instrumentation->AccumulateAndClearMainThreadStats();
208 layer_tree_host_->CommitComplete();
209 next_frame_is_newly_committed_frame_ = true;
212 void SingleThreadProxy::SetNeedsCommit() {
213 DCHECK(Proxy::IsMainThread());
214 client_->ScheduleComposite();
217 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
218 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
219 SetNeedsRedrawRectOnImplThread(damage_rect);
220 client_->ScheduleComposite();
223 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
224 // There is no activation here other than commit. So do nothing.
227 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
228 // Thread-only feature.
229 NOTREACHED();
232 bool SingleThreadProxy::CommitRequested() const { return false; }
234 bool SingleThreadProxy::BeginMainFrameRequested() const { return false; }
236 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
237 return std::numeric_limits<size_t>::max();
240 void SingleThreadProxy::Stop() {
241 TRACE_EVENT0("cc", "SingleThreadProxy::stop");
242 DCHECK(Proxy::IsMainThread());
244 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
245 DebugScopedSetImplThread impl(this);
247 layer_tree_host_->DeleteContentsTexturesOnImplThread(
248 layer_tree_host_impl_->resource_provider());
249 layer_tree_host_impl_.reset();
251 layer_tree_host_ = NULL;
254 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
255 TRACE_EVENT1(
256 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
257 DCHECK(Proxy::IsImplThread());
258 UpdateBackgroundAnimateTicking();
261 void SingleThreadProxy::NotifyReadyToActivate() {
262 // Thread-only feature.
263 NOTREACHED();
266 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
267 client_->ScheduleComposite();
270 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
271 SetNeedsRedrawOnImplThread();
274 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
275 // Thread-only/Impl-side-painting-only feature.
276 NOTREACHED();
279 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
280 const gfx::Rect& damage_rect) {
281 // TODO(brianderson): Once we move render_widget scheduling into this class,
282 // we can treat redraw requests more efficiently than CommitAndRedraw
283 // requests.
284 layer_tree_host_impl_->SetViewportDamage(damage_rect);
285 SetNeedsCommit();
288 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
289 // Impl-side painting only.
290 NOTREACHED();
293 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
294 client_->ScheduleComposite();
297 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
298 scoped_ptr<AnimationEventsVector> events) {
299 TRACE_EVENT0(
300 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
301 DCHECK(Proxy::IsImplThread());
302 DebugScopedSetMainThread main(this);
303 layer_tree_host_->SetAnimationEvents(events.Pass());
306 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
307 size_t limit_bytes,
308 int priority_cutoff) {
309 DCHECK(IsImplThread());
310 PrioritizedResourceManager* contents_texture_manager =
311 layer_tree_host_->contents_texture_manager();
313 ResourceProvider* resource_provider =
314 layer_tree_host_impl_->resource_provider();
316 if (!contents_texture_manager || !resource_provider)
317 return false;
319 return contents_texture_manager->ReduceMemoryOnImplThread(
320 limit_bytes, priority_cutoff, resource_provider);
323 void SingleThreadProxy::SendManagedMemoryStats() {
324 DCHECK(Proxy::IsImplThread());
325 if (!layer_tree_host_impl_)
326 return;
327 PrioritizedResourceManager* contents_texture_manager =
328 layer_tree_host_->contents_texture_manager();
329 if (!contents_texture_manager)
330 return;
332 layer_tree_host_impl_->SendManagedMemoryStats(
333 contents_texture_manager->MemoryVisibleBytes(),
334 contents_texture_manager->MemoryVisibleAndNearbyBytes(),
335 contents_texture_manager->MemoryUseBytes());
338 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
340 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
341 DCHECK(IsImplThread());
342 renderer_capabilities_for_main_thread_ =
343 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
346 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
347 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
348 // Cause a commit so we can notice the lost context.
349 SetNeedsCommitOnImplThread();
350 client_->DidAbortSwapBuffers();
353 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
354 client_->DidPostSwapBuffers();
357 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
358 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
359 client_->DidCompleteSwapBuffers();
362 // Called by the legacy scheduling path (e.g. where render_widget does the
363 // scheduling)
364 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
365 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
366 gfx::Rect device_viewport_damage_rect;
368 LayerTreeHostImpl::FrameData frame;
369 if (CommitAndComposite(frame_begin_time,
370 device_viewport_damage_rect,
371 false, // for_readback
372 &frame)) {
374 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
375 DebugScopedSetImplThread impl(this);
377 // This CapturePostTasks should be destroyed before
378 // DidCommitAndDrawFrame() is called since that goes out to the embedder,
379 // and we want the embedder to receive its callbacks before that.
380 // NOTE: This maintains consistent ordering with the ThreadProxy since
381 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
382 // there as the main thread is not blocked, so any posted tasks inside
383 // the swap buffers will execute first.
384 BlockingTaskRunner::CapturePostTasks blocked;
386 layer_tree_host_impl_->SwapBuffers(frame);
388 DidSwapFrame();
392 scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
393 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
395 // The following line casts away const modifiers because it is just
396 // setting debug state. We still want the AsValue() function and its
397 // call chain to be const throughout.
398 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
400 state->Set("layer_tree_host_impl",
401 layer_tree_host_impl_->AsValue().release());
403 return state.PassAs<base::Value>();
406 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
408 DebugScopedSetImplThread impl(this);
409 if (layer_tree_host_impl_->renderer()) {
410 DCHECK(!layer_tree_host_->output_surface_lost());
411 layer_tree_host_impl_->renderer()->DoNoOp();
416 bool SingleThreadProxy::CommitAndComposite(
417 base::TimeTicks frame_begin_time,
418 const gfx::Rect& device_viewport_damage_rect,
419 bool for_readback,
420 LayerTreeHostImpl::FrameData* frame) {
421 TRACE_EVENT0("cc", "SingleThreadProxy::CommitAndComposite");
422 DCHECK(Proxy::IsMainThread());
424 if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded())
425 return false;
427 layer_tree_host_->AnimateLayers(frame_begin_time);
429 if (PrioritizedResourceManager* contents_texture_manager =
430 layer_tree_host_->contents_texture_manager()) {
431 contents_texture_manager->UnlinkAndClearEvictedBackings();
432 contents_texture_manager->SetMaxMemoryLimitBytes(
433 layer_tree_host_impl_->memory_allocation_limit_bytes());
434 contents_texture_manager->SetExternalPriorityCutoff(
435 layer_tree_host_impl_->memory_allocation_priority_cutoff());
438 scoped_ptr<ResourceUpdateQueue> queue =
439 make_scoped_ptr(new ResourceUpdateQueue);
440 layer_tree_host_->UpdateLayers(queue.get());
442 layer_tree_host_->WillCommit();
444 DoCommit(queue.Pass());
445 bool result = DoComposite(
446 frame_begin_time, device_viewport_damage_rect, for_readback, frame);
447 layer_tree_host_->DidBeginMainFrame();
448 return result;
451 bool SingleThreadProxy::ShouldComposite() const {
452 DCHECK(Proxy::IsImplThread());
453 return layer_tree_host_impl_->visible() &&
454 layer_tree_host_impl_->CanDraw();
457 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
458 DCHECK(Proxy::IsImplThread());
459 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
460 !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
463 bool SingleThreadProxy::DoComposite(
464 base::TimeTicks frame_begin_time,
465 const gfx::Rect& device_viewport_damage_rect,
466 bool for_readback,
467 LayerTreeHostImpl::FrameData* frame) {
468 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
469 DCHECK(!layer_tree_host_->output_surface_lost());
471 bool lost_output_surface = false;
473 DebugScopedSetImplThread impl(this);
474 base::AutoReset<bool> mark_inside(&inside_draw_, true);
476 bool can_do_readback = layer_tree_host_impl_->renderer()->CanReadPixels();
478 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
479 // frame, so can only be used when such a frame is possible. Since
480 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
481 // CanDraw() as well.
482 if (!ShouldComposite() || (for_readback && !can_do_readback)) {
483 UpdateBackgroundAnimateTicking();
484 return false;
487 layer_tree_host_impl_->Animate(
488 layer_tree_host_impl_->CurrentFrameTimeTicks());
489 UpdateBackgroundAnimateTicking();
491 if (!layer_tree_host_impl_->IsContextLost()) {
492 layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
493 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
494 layer_tree_host_impl_->DidDrawAllLayers(*frame);
496 lost_output_surface = layer_tree_host_impl_->IsContextLost();
498 bool start_ready_animations = true;
499 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
501 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
504 if (lost_output_surface) {
505 layer_tree_host_->DidLoseOutputSurface();
506 return false;
509 return true;
512 void SingleThreadProxy::DidSwapFrame() {
513 if (next_frame_is_newly_committed_frame_) {
514 next_frame_is_newly_committed_frame_ = false;
515 layer_tree_host_->DidCommitAndDrawFrame();
519 bool SingleThreadProxy::CommitPendingForTesting() { return false; }
521 } // namespace cc