Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / cc / trees / single_thread_proxy.cc
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.
4
5 #include "cc/trees/single_thread_proxy.h"
6
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"
20
21 namespace cc {
22
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>();
28 }
29
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);
41
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.";
45 }
46
47 void SingleThreadProxy::Start() {
48   DebugScopedSetImplThread impl(this);
49   layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
50 }
51
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_);
57 }
58
59 bool SingleThreadProxy::CompositeAndReadback(void* pixels,
60                                              const gfx::Rect& rect) {
61   TRACE_EVENT0("cc", "SingleThreadProxy::CompositeAndReadback");
62   DCHECK(Proxy::IsMainThread());
63
64   gfx::Rect device_viewport_damage_rect = rect;
65
66   LayerTreeHostImpl::FrameData frame;
67   if (!CommitAndComposite(gfx::FrameTime::Now(),
68                           device_viewport_damage_rect,
69                           true,  // for_readback
70                           &frame))
71     return false;
72
73   {
74     DebugScopedSetImplThread impl(this);
75     layer_tree_host_impl_->Readback(pixels, rect);
76
77     if (layer_tree_host_impl_->IsContextLost())
78       return false;
79   }
80
81   return true;
82 }
83
84 void SingleThreadProxy::FinishAllRendering() {
85   TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
86   DCHECK(Proxy::IsMainThread());
87   {
88     DebugScopedSetImplThread impl(this);
89     layer_tree_host_impl_->FinishAllRendering();
90   }
91 }
92
93 bool SingleThreadProxy::IsStarted() const {
94   DCHECK(Proxy::IsMainThread());
95   return layer_tree_host_impl_;
96 }
97
98 void SingleThreadProxy::SetLayerTreeHostClientReady() {
99   TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
100   // Scheduling is controlled by the embedder in the single thread case, so
101   // nothing to do.
102 }
103
104 void SingleThreadProxy::SetVisible(bool visible) {
105   TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
106   DebugScopedSetImplThread impl(this);
107   layer_tree_host_impl_->SetVisible(visible);
108
109   // Changing visibility could change ShouldComposite().
110   UpdateBackgroundAnimateTicking();
111 }
112
113 void SingleThreadProxy::CreateAndInitializeOutputSurface() {
114   TRACE_EVENT0(
115       "cc", "SingleThreadProxy::CreateAndInitializeOutputSurface");
116   DCHECK(Proxy::IsMainThread());
117
118   scoped_ptr<OutputSurface> output_surface =
119       layer_tree_host_->CreateOutputSurface();
120   if (!output_surface) {
121     OnOutputSurfaceInitializeAttempted(false);
122     return;
123   }
124
125   scoped_refptr<ContextProvider> offscreen_context_provider;
126   if (created_offscreen_context_provider_) {
127     offscreen_context_provider =
128         layer_tree_host_->client()->OffscreenContextProvider();
129     if (!offscreen_context_provider.get() ||
130         !offscreen_context_provider->BindToCurrentThread()) {
131       OnOutputSurfaceInitializeAttempted(false);
132       return;
133     }
134   }
135
136   {
137     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
138     DebugScopedSetImplThread impl(this);
139     layer_tree_host_->DeleteContentsTexturesOnImplThread(
140         layer_tree_host_impl_->resource_provider());
141   }
142
143   bool initialized;
144   {
145     DebugScopedSetImplThread impl(this);
146
147     DCHECK(output_surface);
148     initialized = layer_tree_host_impl_->InitializeRenderer(
149         output_surface.Pass());
150     if (!initialized && offscreen_context_provider.get()) {
151       offscreen_context_provider->VerifyContexts();
152       offscreen_context_provider = NULL;
153     }
154
155     layer_tree_host_impl_->SetOffscreenContextProvider(
156         offscreen_context_provider);
157   }
158
159   OnOutputSurfaceInitializeAttempted(initialized);
160 }
161
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();
168   }
169 }
170
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_;
175 }
176
177 void SingleThreadProxy::SetNeedsAnimate() {
178   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
179   DCHECK(Proxy::IsMainThread());
180   client_->ScheduleAnimation();
181 }
182
183 void SingleThreadProxy::SetNeedsUpdateLayers() {
184   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
185   DCHECK(Proxy::IsMainThread());
186   client_->ScheduleComposite();
187 }
188
189 void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
190   TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
191   DCHECK(Proxy::IsMainThread());
192   // Commit immediately.
193   {
194     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
195     DebugScopedSetImplThread impl(this);
196
197     // This CapturePostTasks should be destroyed before CommitComplete() is
198     // called since that goes out to the embedder, and we want the embedder
199     // to receive its callbacks before that.
200     BlockingTaskRunner::CapturePostTasks blocked;
201
202     layer_tree_host_impl_->BeginCommit();
203
204     if (PrioritizedResourceManager* contents_texture_manager =
205         layer_tree_host_->contents_texture_manager()) {
206       contents_texture_manager->PushTexturePrioritiesToBackings();
207     }
208     layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
209
210     scoped_ptr<ResourceUpdateController> update_controller =
211         ResourceUpdateController::Create(
212             NULL,
213             Proxy::MainThreadTaskRunner(),
214             queue.Pass(),
215             layer_tree_host_impl_->resource_provider());
216     update_controller->Finalize();
217
218     if (layer_tree_host_impl_->EvictedUIResourcesExist())
219       layer_tree_host_->RecreateUIResources();
220
221     layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
222
223     layer_tree_host_impl_->CommitComplete();
224
225 #ifndef NDEBUG
226     // In the single-threaded case, the scale and scroll deltas should never be
227     // touched on the impl layer tree.
228     scoped_ptr<ScrollAndScaleSet> scroll_info =
229         layer_tree_host_impl_->ProcessScrollDeltas();
230     DCHECK(!scroll_info->scrolls.size());
231     DCHECK_EQ(1.f, scroll_info->page_scale_delta);
232 #endif
233
234     RenderingStatsInstrumentation* stats_instrumentation =
235         layer_tree_host_->rendering_stats_instrumentation();
236     BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
237         stats_instrumentation->main_thread_rendering_stats());
238     stats_instrumentation->AccumulateAndClearMainThreadStats();
239   }
240   layer_tree_host_->CommitComplete();
241   next_frame_is_newly_committed_frame_ = true;
242 }
243
244 void SingleThreadProxy::SetNeedsCommit() {
245   DCHECK(Proxy::IsMainThread());
246   client_->ScheduleComposite();
247 }
248
249 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
250   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
251   SetNeedsRedrawRectOnImplThread(damage_rect);
252   client_->ScheduleComposite();
253 }
254
255 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
256   // There is no activation here other than commit. So do nothing.
257 }
258
259 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
260   // Thread-only feature.
261   NOTREACHED();
262 }
263
264 bool SingleThreadProxy::CommitRequested() const { return false; }
265
266 bool SingleThreadProxy::BeginMainFrameRequested() const { return false; }
267
268 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
269   return std::numeric_limits<size_t>::max();
270 }
271
272 void SingleThreadProxy::Stop() {
273   TRACE_EVENT0("cc", "SingleThreadProxy::stop");
274   DCHECK(Proxy::IsMainThread());
275   {
276     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
277     DebugScopedSetImplThread impl(this);
278
279     layer_tree_host_->DeleteContentsTexturesOnImplThread(
280         layer_tree_host_impl_->resource_provider());
281     layer_tree_host_impl_.reset();
282   }
283   layer_tree_host_ = NULL;
284 }
285
286 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
287   TRACE_EVENT1(
288       "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
289   DCHECK(Proxy::IsImplThread());
290   UpdateBackgroundAnimateTicking();
291 }
292
293 void SingleThreadProxy::NotifyReadyToActivate() {
294   // Thread-only feature.
295   NOTREACHED();
296 }
297
298 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
299   client_->ScheduleComposite();
300 }
301
302 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
303   // Thread-only/Impl-side-painting-only feature.
304   NOTREACHED();
305 }
306
307 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
308     const gfx::Rect& damage_rect) {
309   // TODO(brianderson): Once we move render_widget scheduling into this class,
310   // we can treat redraw requests more efficiently than CommitAndRedraw
311   // requests.
312   layer_tree_host_impl_->SetViewportDamage(damage_rect);
313   SetNeedsCommit();
314 }
315
316 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
317   // Impl-side painting only.
318   NOTREACHED();
319 }
320
321 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
322   client_->ScheduleComposite();
323 }
324
325 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
326     scoped_ptr<AnimationEventsVector> events,
327     base::Time wall_clock_time) {
328   TRACE_EVENT0(
329       "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
330   DCHECK(Proxy::IsImplThread());
331   DebugScopedSetMainThread main(this);
332   layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
333 }
334
335 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
336     size_t limit_bytes,
337     int priority_cutoff) {
338   DCHECK(IsImplThread());
339   PrioritizedResourceManager* contents_texture_manager =
340       layer_tree_host_->contents_texture_manager();
341
342   ResourceProvider* resource_provider =
343       layer_tree_host_impl_->resource_provider();
344
345   if (!contents_texture_manager || !resource_provider)
346     return false;
347
348   return contents_texture_manager->ReduceMemoryOnImplThread(
349       limit_bytes, priority_cutoff, resource_provider);
350 }
351
352 void SingleThreadProxy::SendManagedMemoryStats() {
353   DCHECK(Proxy::IsImplThread());
354   if (!layer_tree_host_impl_)
355     return;
356   PrioritizedResourceManager* contents_texture_manager =
357       layer_tree_host_->contents_texture_manager();
358   if (!contents_texture_manager)
359     return;
360
361   layer_tree_host_impl_->SendManagedMemoryStats(
362       contents_texture_manager->MemoryVisibleBytes(),
363       contents_texture_manager->MemoryVisibleAndNearbyBytes(),
364       contents_texture_manager->MemoryUseBytes());
365 }
366
367 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
368
369 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
370   DCHECK(IsImplThread());
371   renderer_capabilities_for_main_thread_ =
372       layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
373 }
374
375 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
376   TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
377   // Cause a commit so we can notice the lost context.
378   SetNeedsCommitOnImplThread();
379   client_->DidAbortSwapBuffers();
380 }
381
382 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
383   client_->DidPostSwapBuffers();
384 }
385
386 void SingleThreadProxy::OnSwapBuffersCompleteOnImplThread() {
387   TRACE_EVENT0("cc", "SingleThreadProxy::OnSwapBuffersCompleteOnImplThread");
388   client_->DidCompleteSwapBuffers();
389 }
390
391 // Called by the legacy scheduling path (e.g. where render_widget does the
392 // scheduling)
393 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
394   TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
395   gfx::Rect device_viewport_damage_rect;
396
397   LayerTreeHostImpl::FrameData frame;
398   if (CommitAndComposite(frame_begin_time,
399                          device_viewport_damage_rect,
400                          false,  // for_readback
401                          &frame)) {
402     {
403       DebugScopedSetMainThreadBlocked main_thread_blocked(this);
404       DebugScopedSetImplThread impl(this);
405
406       // This CapturePostTasks should be destroyed before
407       // DidCommitAndDrawFrame() is called since that goes out to the embedder,
408       // and we want the embedder to receive its callbacks before that.
409       // NOTE: This maintains consistent ordering with the ThreadProxy since
410       // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
411       // there as the main thread is not blocked, so any posted tasks inside
412       // the swap buffers will execute first.
413       BlockingTaskRunner::CapturePostTasks blocked;
414
415       layer_tree_host_impl_->SwapBuffers(frame);
416     }
417     DidSwapFrame();
418   }
419 }
420
421 scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
422   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
423   {
424     // The following line casts away const modifiers because it is just
425     // setting debug state. We still want the AsValue() function and its
426     // call chain to be const throughout.
427     DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
428
429     state->Set("layer_tree_host_impl",
430                layer_tree_host_impl_->AsValue().release());
431   }
432   return state.PassAs<base::Value>();
433 }
434
435 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
436   {
437     DebugScopedSetImplThread impl(this);
438     if (layer_tree_host_impl_->renderer()) {
439       DCHECK(!layer_tree_host_->output_surface_lost());
440       layer_tree_host_impl_->renderer()->DoNoOp();
441     }
442   }
443 }
444
445 bool SingleThreadProxy::CommitAndComposite(
446     base::TimeTicks frame_begin_time,
447     const gfx::Rect& device_viewport_damage_rect,
448     bool for_readback,
449     LayerTreeHostImpl::FrameData* frame) {
450   TRACE_EVENT0("cc", "SingleThreadProxy::CommitAndComposite");
451   DCHECK(Proxy::IsMainThread());
452
453   if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded())
454     return false;
455
456   layer_tree_host_->AnimateLayers(frame_begin_time);
457
458   if (PrioritizedResourceManager* contents_texture_manager =
459       layer_tree_host_->contents_texture_manager()) {
460     contents_texture_manager->UnlinkAndClearEvictedBackings();
461     contents_texture_manager->SetMaxMemoryLimitBytes(
462         layer_tree_host_impl_->memory_allocation_limit_bytes());
463     contents_texture_manager->SetExternalPriorityCutoff(
464         layer_tree_host_impl_->memory_allocation_priority_cutoff());
465   }
466
467   scoped_ptr<ResourceUpdateQueue> queue =
468       make_scoped_ptr(new ResourceUpdateQueue);
469   layer_tree_host_->UpdateLayers(queue.get());
470
471   layer_tree_host_->WillCommit();
472
473   scoped_refptr<ContextProvider> offscreen_context_provider;
474   if (renderer_capabilities_for_main_thread_.using_offscreen_context3d &&
475       layer_tree_host_->needs_offscreen_context()) {
476     offscreen_context_provider =
477         layer_tree_host_->client()->OffscreenContextProvider();
478     if (offscreen_context_provider.get() &&
479         !offscreen_context_provider->BindToCurrentThread())
480       offscreen_context_provider = NULL;
481
482     if (offscreen_context_provider.get())
483       created_offscreen_context_provider_ = true;
484   }
485
486   DoCommit(queue.Pass());
487   bool result = DoComposite(offscreen_context_provider,
488                             frame_begin_time,
489                             device_viewport_damage_rect,
490                             for_readback,
491                             frame);
492   layer_tree_host_->DidBeginMainFrame();
493   return result;
494 }
495
496 bool SingleThreadProxy::ShouldComposite() const {
497   DCHECK(Proxy::IsImplThread());
498   return layer_tree_host_impl_->visible() &&
499          layer_tree_host_impl_->CanDraw();
500 }
501
502 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
503   DCHECK(Proxy::IsImplThread());
504   layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
505       !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
506 }
507
508 bool SingleThreadProxy::DoComposite(
509     scoped_refptr<ContextProvider> offscreen_context_provider,
510     base::TimeTicks frame_begin_time,
511     const gfx::Rect& device_viewport_damage_rect,
512     bool for_readback,
513     LayerTreeHostImpl::FrameData* frame) {
514   TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
515   DCHECK(!layer_tree_host_->output_surface_lost());
516
517   bool lost_output_surface = false;
518   {
519     DebugScopedSetImplThread impl(this);
520     base::AutoReset<bool> mark_inside(&inside_draw_, true);
521
522     layer_tree_host_impl_->SetOffscreenContextProvider(
523         offscreen_context_provider);
524
525     bool can_do_readback = layer_tree_host_impl_->renderer()->CanReadPixels();
526
527     // We guard PrepareToDraw() with CanDraw() because it always returns a valid
528     // frame, so can only be used when such a frame is possible. Since
529     // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
530     // CanDraw() as well.
531     if (!ShouldComposite() || (for_readback && !can_do_readback)) {
532       UpdateBackgroundAnimateTicking();
533       return false;
534     }
535
536     layer_tree_host_impl_->Animate(
537         layer_tree_host_impl_->CurrentFrameTimeTicks(),
538         layer_tree_host_impl_->CurrentFrameTime());
539     UpdateBackgroundAnimateTicking();
540
541     if (!layer_tree_host_impl_->IsContextLost()) {
542       layer_tree_host_impl_->PrepareToDraw(frame, device_viewport_damage_rect);
543       layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
544       layer_tree_host_impl_->DidDrawAllLayers(*frame);
545     }
546     lost_output_surface = layer_tree_host_impl_->IsContextLost();
547
548     bool start_ready_animations = true;
549     layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
550
551     layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
552   }
553
554   if (lost_output_surface) {
555     ContextProvider* offscreen_contexts =
556         layer_tree_host_impl_->offscreen_context_provider();
557     if (offscreen_contexts)
558       offscreen_contexts->VerifyContexts();
559     layer_tree_host_->DidLoseOutputSurface();
560     return false;
561   }
562
563   return true;
564 }
565
566 void SingleThreadProxy::DidSwapFrame() {
567   if (next_frame_is_newly_committed_frame_) {
568     next_frame_is_newly_committed_frame_ = false;
569     layer_tree_host_->DidCommitAndDrawFrame();
570   }
571 }
572
573 bool SingleThreadProxy::CommitPendingForTesting() { return false; }
574
575 }  // namespace cc