Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / compositor_impl_android.cc
1 // Copyright (c) 2012 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 "content/browser/renderer_host/compositor_impl_android.h"
6
7 #include <android/bitmap.h>
8 #include <android/native_window_jni.h>
9
10 #include "base/android/jni_android.h"
11 #include "base/android/scoped_java_ref.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/containers/hash_tables.h"
15 #include "base/lazy_instance.h"
16 #include "base/logging.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/synchronization/lock.h"
19 #include "base/threading/thread.h"
20 #include "base/threading/thread_checker.h"
21 #include "cc/base/switches.h"
22 #include "cc/input/input_handler.h"
23 #include "cc/layers/layer.h"
24 #include "cc/output/compositor_frame.h"
25 #include "cc/output/context_provider.h"
26 #include "cc/output/output_surface.h"
27 #include "cc/trees/layer_tree_host.h"
28 #include "content/browser/android/child_process_launcher_android.h"
29 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
30 #include "content/browser/gpu/gpu_surface_tracker.h"
31 #include "content/common/gpu/client/command_buffer_proxy_impl.h"
32 #include "content/common/gpu/client/context_provider_command_buffer.h"
33 #include "content/common/gpu/client/gl_helper.h"
34 #include "content/common/gpu/client/gpu_channel_host.h"
35 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
36 #include "content/common/gpu/gpu_process_launch_causes.h"
37 #include "content/common/host_shared_bitmap_manager.h"
38 #include "content/public/browser/android/compositor_client.h"
39 #include "gpu/command_buffer/client/gles2_interface.h"
40 #include "third_party/khronos/GLES2/gl2.h"
41 #include "third_party/khronos/GLES2/gl2ext.h"
42 #include "third_party/skia/include/core/SkMallocPixelRef.h"
43 #include "ui/base/android/window_android.h"
44 #include "ui/gfx/android/device_display_info.h"
45 #include "ui/gfx/frame_time.h"
46 #include "ui/gl/android/surface_texture.h"
47 #include "ui/gl/android/surface_texture_tracker.h"
48 #include "webkit/common/gpu/context_provider_in_process.h"
49 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
50
51 namespace {
52
53 const unsigned int kMaxSwapBuffers = 2U;
54
55 // Used to override capabilities_.adjust_deadline_for_parent to false
56 class OutputSurfaceWithoutParent : public cc::OutputSurface {
57  public:
58   OutputSurfaceWithoutParent(const scoped_refptr<
59       content::ContextProviderCommandBuffer>& context_provider)
60       : cc::OutputSurface(context_provider) {
61     capabilities_.adjust_deadline_for_parent = false;
62   }
63
64   virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
65     content::ContextProviderCommandBuffer* provider_command_buffer =
66         static_cast<content::ContextProviderCommandBuffer*>(
67             context_provider_.get());
68     content::CommandBufferProxyImpl* command_buffer_proxy =
69         provider_command_buffer->GetCommandBufferProxy();
70     DCHECK(command_buffer_proxy);
71     command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
72
73     OutputSurface::SwapBuffers(frame);
74   }
75 };
76
77 class SurfaceTextureTrackerImpl : public gfx::SurfaceTextureTracker {
78  public:
79   SurfaceTextureTrackerImpl() : next_surface_texture_id_(1) {
80     thread_checker_.DetachFromThread();
81   }
82
83   // Overridden from gfx::SurfaceTextureTracker:
84   virtual scoped_refptr<gfx::SurfaceTexture> AcquireSurfaceTexture(
85       int primary_id,
86       int secondary_id) OVERRIDE {
87     base::AutoLock lock(surface_textures_lock_);
88     SurfaceTextureMapKey key(primary_id, secondary_id);
89     SurfaceTextureMap::iterator it = surface_textures_.find(key);
90     if (it == surface_textures_.end())
91       return scoped_refptr<gfx::SurfaceTexture>();
92     scoped_refptr<gfx::SurfaceTexture> surface_texture = it->second;
93     surface_textures_.erase(it);
94     return surface_texture;
95   }
96
97   int AddSurfaceTexture(gfx::SurfaceTexture* surface_texture,
98                         int child_process_id) {
99     DCHECK(thread_checker_.CalledOnValidThread());
100     int surface_texture_id = next_surface_texture_id_++;
101     if (next_surface_texture_id_ == INT_MAX)
102       next_surface_texture_id_ = 1;
103
104     base::AutoLock lock(surface_textures_lock_);
105     SurfaceTextureMapKey key(surface_texture_id, child_process_id);
106     DCHECK(surface_textures_.find(key) == surface_textures_.end());
107     surface_textures_[key] = surface_texture;
108     content::RegisterChildProcessSurfaceTexture(
109         surface_texture_id,
110         child_process_id,
111         surface_texture->j_surface_texture().obj());
112     return surface_texture_id;
113   }
114
115   void RemoveAllSurfaceTextures(int child_process_id) {
116     DCHECK(thread_checker_.CalledOnValidThread());
117     base::AutoLock lock(surface_textures_lock_);
118     SurfaceTextureMap::iterator it = surface_textures_.begin();
119     while (it != surface_textures_.end()) {
120       if (it->first.second == child_process_id) {
121         content::UnregisterChildProcessSurfaceTexture(it->first.first,
122                                                       it->first.second);
123         surface_textures_.erase(it++);
124       } else {
125         ++it;
126       }
127     }
128   }
129
130  private:
131   typedef std::pair<int, int> SurfaceTextureMapKey;
132   typedef base::hash_map<SurfaceTextureMapKey,
133                          scoped_refptr<gfx::SurfaceTexture> >
134       SurfaceTextureMap;
135   SurfaceTextureMap surface_textures_;
136   mutable base::Lock surface_textures_lock_;
137   int next_surface_texture_id_;
138   base::ThreadChecker thread_checker_;
139 };
140 base::LazyInstance<SurfaceTextureTrackerImpl> g_surface_texture_tracker =
141     LAZY_INSTANCE_INITIALIZER;
142
143 static bool g_initialized = false;
144
145 } // anonymous namespace
146
147 namespace content {
148
149 // static
150 Compositor* Compositor::Create(CompositorClient* client,
151                                gfx::NativeWindow root_window) {
152   return client ? new CompositorImpl(client, root_window) : NULL;
153 }
154
155 // static
156 void Compositor::Initialize() {
157   DCHECK(!CompositorImpl::IsInitialized());
158   // SurfaceTextureTracker instance must be set before we create a GPU thread
159   // that could be using it to initialize GLImage instances.
160   gfx::SurfaceTextureTracker::InitInstance(g_surface_texture_tracker.Pointer());
161   g_initialized = true;
162 }
163
164 // static
165 bool CompositorImpl::IsInitialized() {
166   return g_initialized;
167 }
168
169 // static
170 int CompositorImpl::CreateSurfaceTexture(int child_process_id) {
171   // Note: this needs to be 0 as the surface texture implemenation will take
172   // ownership of the texture and call glDeleteTextures when the GPU service
173   // attaches the surface texture to a real texture id. glDeleteTextures
174   // silently ignores 0.
175   const int kDummyTextureId = 0;
176   scoped_refptr<gfx::SurfaceTexture> surface_texture =
177       gfx::SurfaceTexture::Create(kDummyTextureId);
178   return g_surface_texture_tracker.Pointer()->AddSurfaceTexture(
179       surface_texture.get(), child_process_id);
180 }
181
182 // static
183 void CompositorImpl::DestroyAllSurfaceTextures(int child_process_id) {
184   g_surface_texture_tracker.Pointer()->RemoveAllSurfaceTextures(
185       child_process_id);
186 }
187
188 CompositorImpl::CompositorImpl(CompositorClient* client,
189                                gfx::NativeWindow root_window)
190     : root_layer_(cc::Layer::Create()),
191       has_transparent_background_(false),
192       device_scale_factor_(1),
193       window_(NULL),
194       surface_id_(0),
195       client_(client),
196       root_window_(root_window),
197       did_post_swapbuffers_(false),
198       ignore_schedule_composite_(false),
199       needs_composite_(false),
200       needs_animate_(false),
201       will_composite_immediately_(false),
202       composite_on_vsync_trigger_(DO_NOT_COMPOSITE),
203       pending_swapbuffers_(0U),
204       weak_factory_(this) {
205   DCHECK(client);
206   DCHECK(root_window);
207   ImageTransportFactoryAndroid::AddObserver(this);
208   root_window->AttachCompositor(this);
209 }
210
211 CompositorImpl::~CompositorImpl() {
212   root_window_->DetachCompositor();
213   ImageTransportFactoryAndroid::RemoveObserver(this);
214   // Clean-up any surface references.
215   SetSurface(NULL);
216 }
217
218 void CompositorImpl::PostComposite(CompositingTrigger trigger) {
219   DCHECK(needs_composite_);
220   DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
221
222   if (will_composite_immediately_ ||
223       (trigger == COMPOSITE_EVENTUALLY && WillComposite())) {
224     // We will already composite soon enough.
225     DCHECK(WillComposite());
226     return;
227   }
228
229   if (DidCompositeThisFrame()) {
230     DCHECK(!WillCompositeThisFrame());
231     if (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) {
232       composite_on_vsync_trigger_ = trigger;
233       root_window_->RequestVSyncUpdate();
234     }
235     DCHECK(WillComposite());
236     return;
237   }
238
239   base::TimeDelta delay;
240   if (trigger == COMPOSITE_IMMEDIATELY) {
241     will_composite_immediately_ = true;
242     composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
243   } else {
244     DCHECK(!WillComposite());
245     const base::TimeDelta estimated_composite_time = vsync_period_ / 4;
246     const base::TimeTicks now = base::TimeTicks::Now();
247
248     if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) {
249       base::TimeTicks next_composite =
250           last_vsync_ + vsync_period_ - estimated_composite_time;
251       if (next_composite < now) {
252         // It's too late, we will reschedule composite as needed on the next
253         // vsync.
254         composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
255         root_window_->RequestVSyncUpdate();
256         DCHECK(WillComposite());
257         return;
258       }
259
260       delay = next_composite - now;
261     }
262   }
263   TRACE_EVENT2("cc", "CompositorImpl::PostComposite",
264                "trigger", trigger,
265                "delay", delay.InMillisecondsF());
266
267   DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE);
268   if (current_composite_task_)
269     current_composite_task_->Cancel();
270
271   // Unretained because we cancel the task on shutdown.
272   current_composite_task_.reset(new base::CancelableClosure(
273       base::Bind(&CompositorImpl::Composite, base::Unretained(this), trigger)));
274   base::MessageLoop::current()->PostDelayedTask(
275       FROM_HERE, current_composite_task_->callback(), delay);
276 }
277
278 void CompositorImpl::Composite(CompositingTrigger trigger) {
279   BrowserGpuChannelHostFactory* factory =
280       BrowserGpuChannelHostFactory::instance();
281   if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
282     CauseForGpuLaunch cause =
283         CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
284     factory->EstablishGpuChannel(
285         cause,
286         base::Bind(&CompositorImpl::OnGpuChannelEstablished,
287                    weak_factory_.GetWeakPtr()));
288     return;
289   }
290
291   DCHECK(host_);
292   DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY);
293   DCHECK(needs_composite_);
294   DCHECK(!DidCompositeThisFrame());
295
296   if (trigger == COMPOSITE_IMMEDIATELY)
297     will_composite_immediately_ = false;
298
299   DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers);
300   if (pending_swapbuffers_ == kMaxSwapBuffers) {
301     TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit");
302     return;
303   }
304
305   // Reset state before Layout+Composite since that might create more
306   // requests to Composite that we need to respect.
307   needs_composite_ = false;
308
309   // Only allow compositing once per vsync.
310   current_composite_task_->Cancel();
311   DCHECK(DidCompositeThisFrame() && !WillComposite());
312
313   // Ignore ScheduleComposite() from layer tree changes during layout and
314   // animation updates that will already be reflected in the current frame
315   // we are about to draw.
316   ignore_schedule_composite_ = true;
317   client_->Layout();
318
319   const base::TimeTicks frame_time = gfx::FrameTime::Now();
320   if (needs_animate_) {
321     needs_animate_ = false;
322     root_window_->Animate(frame_time);
323   }
324   ignore_schedule_composite_ = false;
325
326   did_post_swapbuffers_ = false;
327   host_->Composite(frame_time);
328   if (did_post_swapbuffers_)
329     pending_swapbuffers_++;
330
331   // Need to track vsync to avoid compositing more than once per frame.
332   root_window_->RequestVSyncUpdate();
333 }
334
335 void CompositorImpl::OnGpuChannelEstablished() {
336   ScheduleComposite();
337 }
338
339 UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
340   return ui_resource_provider_;
341 }
342
343 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
344   if (subroot_layer_) {
345     subroot_layer_->RemoveFromParent();
346     subroot_layer_ = NULL;
347   }
348   if (root_layer) {
349     subroot_layer_ = root_layer;
350     root_layer_->AddChild(root_layer);
351   }
352 }
353
354 void CompositorImpl::SetWindowSurface(ANativeWindow* window) {
355   GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
356
357   if (window_) {
358     tracker->RemoveSurface(surface_id_);
359     ANativeWindow_release(window_);
360     window_ = NULL;
361     surface_id_ = 0;
362     SetVisible(false);
363   }
364
365   if (window) {
366     window_ = window;
367     ANativeWindow_acquire(window);
368     surface_id_ = tracker->AddSurfaceForNativeWidget(window);
369     tracker->SetSurfaceHandle(
370         surface_id_,
371         gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT));
372     SetVisible(true);
373   }
374 }
375
376 void CompositorImpl::SetSurface(jobject surface) {
377   JNIEnv* env = base::android::AttachCurrentThread();
378   base::android::ScopedJavaLocalRef<jobject> j_surface(env, surface);
379
380   // First, cleanup any existing surface references.
381   if (surface_id_)
382     content::UnregisterViewSurface(surface_id_);
383   SetWindowSurface(NULL);
384
385   // Now, set the new surface if we have one.
386   ANativeWindow* window = NULL;
387   if (surface) {
388     // Note: This ensures that any local references used by
389     // ANativeWindow_fromSurface are released immediately. This is needed as a
390     // workaround for https://code.google.com/p/android/issues/detail?id=68174
391     base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
392     window = ANativeWindow_fromSurface(env, surface);
393   }
394   if (window) {
395     SetWindowSurface(window);
396     ANativeWindow_release(window);
397     content::RegisterViewSurface(surface_id_, j_surface.obj());
398   }
399 }
400
401 void CompositorImpl::SetVisible(bool visible) {
402   if (!visible) {
403     if (WillComposite())
404       CancelComposite();
405     ui_resource_provider_.SetLayerTreeHost(NULL);
406     host_.reset();
407   } else if (!host_) {
408     DCHECK(!WillComposite());
409     needs_composite_ = false;
410     needs_animate_ = false;
411     pending_swapbuffers_ = 0;
412     cc::LayerTreeSettings settings;
413     settings.refresh_rate = 60.0;
414     settings.impl_side_painting = false;
415     settings.allow_antialiasing = false;
416     settings.calculate_top_controls_position = false;
417     settings.top_controls_height = 0.f;
418     settings.highp_threshold_min = 2048;
419
420     CommandLine* command_line = CommandLine::ForCurrentProcess();
421     settings.initial_debug_state.SetRecordRenderingStats(
422         command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
423     settings.initial_debug_state.show_fps_counter =
424         command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
425
426     host_ = cc::LayerTreeHost::CreateSingleThreaded(
427         this, this, HostSharedBitmapManager::current(), settings);
428     host_->SetRootLayer(root_layer_);
429
430     host_->SetVisible(true);
431     host_->SetLayerTreeHostClientReady();
432     host_->SetViewportSize(size_);
433     host_->set_has_transparent_background(has_transparent_background_);
434     host_->SetDeviceScaleFactor(device_scale_factor_);
435     ui_resource_provider_.SetLayerTreeHost(host_.get());
436   }
437 }
438
439 void CompositorImpl::setDeviceScaleFactor(float factor) {
440   device_scale_factor_ = factor;
441   if (host_)
442     host_->SetDeviceScaleFactor(factor);
443 }
444
445 void CompositorImpl::SetWindowBounds(const gfx::Size& size) {
446   if (size_ == size)
447     return;
448
449   size_ = size;
450   if (host_)
451     host_->SetViewportSize(size);
452   root_layer_->SetBounds(size);
453 }
454
455 void CompositorImpl::SetHasTransparentBackground(bool flag) {
456   has_transparent_background_ = flag;
457   if (host_)
458     host_->set_has_transparent_background(flag);
459 }
460
461 void CompositorImpl::SetNeedsComposite() {
462   if (!host_.get())
463     return;
464   DCHECK(!needs_composite_ || WillComposite());
465
466   needs_composite_ = true;
467   PostComposite(COMPOSITE_IMMEDIATELY);
468 }
469
470 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
471 CreateGpuProcessViewContext(
472     const scoped_refptr<GpuChannelHost>& gpu_channel_host,
473     const blink::WebGraphicsContext3D::Attributes attributes,
474     int surface_id) {
475   DCHECK(gpu_channel_host);
476
477   GURL url("chrome://gpu/Compositor::createContext3D");
478   static const size_t kBytesPerPixel = 4;
479   gfx::DeviceDisplayInfo display_info;
480   size_t full_screen_texture_size_in_bytes =
481       display_info.GetDisplayHeight() *
482       display_info.GetDisplayWidth() *
483       kBytesPerPixel;
484   WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
485   limits.command_buffer_size = 64 * 1024;
486   limits.start_transfer_buffer_size = 64 * 1024;
487   limits.min_transfer_buffer_size = 64 * 1024;
488   limits.max_transfer_buffer_size = std::min(
489       3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
490   limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
491   bool lose_context_when_out_of_memory = true;
492   return make_scoped_ptr(
493       new WebGraphicsContext3DCommandBufferImpl(surface_id,
494                                                 url,
495                                                 gpu_channel_host.get(),
496                                                 attributes,
497                                                 lose_context_when_out_of_memory,
498                                                 limits,
499                                                 NULL));
500 }
501
502 void CompositorImpl::Layout() {
503   // TODO: If we get this callback from the SingleThreadProxy, we need
504   // to stop calling it ourselves in CompositorImpl::Composite().
505   NOTREACHED();
506   client_->Layout();
507 }
508
509 scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
510     bool fallback) {
511   blink::WebGraphicsContext3D::Attributes attrs;
512   attrs.shareResources = true;
513   attrs.noAutomaticFlushes = true;
514   pending_swapbuffers_ = 0;
515
516   DCHECK(window_);
517   DCHECK(surface_id_);
518
519   scoped_refptr<ContextProviderCommandBuffer> context_provider;
520   BrowserGpuChannelHostFactory* factory =
521       BrowserGpuChannelHostFactory::instance();
522   scoped_refptr<GpuChannelHost> gpu_channel_host = factory->GetGpuChannel();
523   if (gpu_channel_host && !gpu_channel_host->IsLost()) {
524     context_provider = ContextProviderCommandBuffer::Create(
525         CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_),
526         "BrowserCompositor");
527   }
528   if (!context_provider.get()) {
529     LOG(ERROR) << "Failed to create 3D context for compositor.";
530     return scoped_ptr<cc::OutputSurface>();
531   }
532
533   return scoped_ptr<cc::OutputSurface>(
534       new OutputSurfaceWithoutParent(context_provider));
535 }
536
537 void CompositorImpl::OnLostResources() {
538   client_->DidLoseResources();
539   ui_resource_provider_.UIResourcesAreInvalid();
540 }
541
542 void CompositorImpl::ScheduleComposite() {
543   DCHECK(!needs_composite_ || WillComposite());
544   if (ignore_schedule_composite_)
545     return;
546
547   needs_composite_ = true;
548   // We currently expect layer tree invalidations at most once per frame
549   // during normal operation and therefore try to composite immediately
550   // to minimize latency.
551   PostComposite(COMPOSITE_IMMEDIATELY);
552 }
553
554 void CompositorImpl::ScheduleAnimation() {
555   DCHECK(!needs_animate_ || needs_composite_);
556   DCHECK(!needs_composite_ || WillComposite());
557   needs_animate_ = true;
558
559   if (needs_composite_)
560     return;
561
562   TRACE_EVENT0("cc", "CompositorImpl::ScheduleAnimation");
563   needs_composite_ = true;
564   PostComposite(COMPOSITE_EVENTUALLY);
565 }
566
567 void CompositorImpl::DidPostSwapBuffers() {
568   TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers");
569   did_post_swapbuffers_ = true;
570 }
571
572 void CompositorImpl::DidCompleteSwapBuffers() {
573   TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers");
574   DCHECK_GT(pending_swapbuffers_, 0U);
575   if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_)
576     PostComposite(COMPOSITE_IMMEDIATELY);
577   client_->OnSwapBuffersCompleted(pending_swapbuffers_);
578 }
579
580 void CompositorImpl::DidAbortSwapBuffers() {
581   TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers");
582   // This really gets called only once from
583   // SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the
584   // context was lost.
585   client_->OnSwapBuffersCompleted(0);
586 }
587
588 void CompositorImpl::DidCommit() {
589   root_window_->OnCompositingDidCommit();
590 }
591
592 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
593   root_layer_->AddChild(layer);
594 }
595
596 void CompositorImpl::RequestCopyOfOutputOnRootLayer(
597     scoped_ptr<cc::CopyOutputRequest> request) {
598   root_layer_->RequestCopyOfOutput(request.Pass());
599 }
600
601 void CompositorImpl::OnVSync(base::TimeTicks frame_time,
602                              base::TimeDelta vsync_period) {
603   vsync_period_ = vsync_period;
604   last_vsync_ = frame_time;
605
606   if (WillCompositeThisFrame()) {
607     // We somehow missed the last vsync interval, so reschedule for deadline.
608     // We cannot schedule immediately, or will get us out-of-phase with new
609     // renderer frames.
610     CancelComposite();
611     composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY;
612   } else {
613     current_composite_task_.reset();
614   }
615
616   DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame());
617   if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) {
618     CompositingTrigger trigger = composite_on_vsync_trigger_;
619     composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
620     PostComposite(trigger);
621   }
622 }
623
624 void CompositorImpl::SetNeedsAnimate() {
625   if (!host_)
626     return;
627
628   host_->SetNeedsAnimate();
629 }
630
631 }  // namespace content