e1675223c548077bf40cbbab3dfebd9f6b2b8285
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCThreadProxy.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCThreadProxy.h"
28
29 #include "GraphicsContext3D.h"
30 #include "TraceEvent.h"
31 #include "cc/CCDelayBasedTimeSource.h"
32 #include "cc/CCFrameRateController.h"
33 #include "cc/CCInputHandler.h"
34 #include "cc/CCLayerTreeHost.h"
35 #include "cc/CCScheduler.h"
36 #include "cc/CCScopedThreadProxy.h"
37 #include "cc/CCTextureUpdater.h"
38 #include "cc/CCThreadTask.h"
39 #include <wtf/CurrentTime.h>
40 #include <wtf/MainThread.h>
41
42 using namespace WTF;
43
44 namespace {
45
46 // Number of textures to update with each call to
47 // scheduledActionUpdateMoreResources().
48 static const size_t textureUpdatesPerFrame = 32;
49
50 } // anonymous namespace
51
52 namespace WebCore {
53
54 PassOwnPtr<CCProxy> CCThreadProxy::create(CCLayerTreeHost* layerTreeHost)
55 {
56     return adoptPtr(new CCThreadProxy(layerTreeHost));
57 }
58
59 CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost)
60     : m_animateRequested(false)
61     , m_commitRequested(false)
62     , m_contextLost(false)
63     , m_layerTreeHost(layerTreeHost)
64     , m_compositorIdentifier(-1)
65     , m_layerRendererInitialized(false)
66     , m_started(false)
67     , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread()))
68     , m_beginFrameCompletionEventOnImplThread(0)
69     , m_readbackRequestOnImplThread(0)
70     , m_finishAllRenderingCompletionEventOnImplThread(0)
71     , m_commitCompletionEventOnImplThread(0)
72     , m_nextFrameIsNewlyCommittedFrameOnImplThread(false)
73 {
74     TRACE_EVENT("CCThreadProxy::CCThreadProxy", this, 0);
75     ASSERT(isMainThread());
76 }
77
78 CCThreadProxy::~CCThreadProxy()
79 {
80     TRACE_EVENT("CCThreadProxy::~CCThreadProxy", this, 0);
81     ASSERT(isMainThread());
82     ASSERT(!m_started);
83 }
84
85 bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
86 {
87     TRACE_EVENT("CCThreadPRoxy::compositeAndReadback", this, 0);
88     ASSERT(isMainThread());
89     ASSERT(m_layerTreeHost);
90
91     if (!m_layerRendererInitialized) {
92         TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0);
93         return false;
94     }
95
96
97     // Perform a synchronous commit.
98     CCCompletionEvent beginFrameCompletion;
99     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, AllowCrossThreadAccess(&beginFrameCompletion)));
100     beginFrameCompletion.wait();
101     beginFrame();
102
103     // Perform a synchronous readback.
104     ReadbackRequest request;
105     request.rect = rect;
106     request.pixels = pixels;
107     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestReadbackOnImplThread, AllowCrossThreadAccess(&request)));
108     request.completion.wait();
109     return request.success;
110 }
111
112 void CCThreadProxy::requestReadbackOnImplThread(ReadbackRequest* request)
113 {
114     ASSERT(CCProxy::isImplThread());
115     ASSERT(!m_readbackRequestOnImplThread);
116     if (!m_layerTreeHostImpl) {
117         request->success = false;
118         request->completion.signal();
119         return;
120     }
121     m_readbackRequestOnImplThread = request;
122     m_schedulerOnImplThread->setNeedsRedraw();
123     m_schedulerOnImplThread->setNeedsForcedRedraw();
124 }
125
126 void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration)
127 {
128     ASSERT(CCProxy::isMainThread());
129     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, duration));
130 }
131
132 void CCThreadProxy::requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double duration)
133 {
134     ASSERT(CCProxy::isImplThread());
135     if (m_layerTreeHostImpl)
136         m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration);
137 }
138
139 GraphicsContext3D* CCThreadProxy::context()
140 {
141     return 0;
142 }
143
144 void CCThreadProxy::finishAllRendering()
145 {
146     ASSERT(CCProxy::isMainThread());
147
148     // Make sure all GL drawing is finished on the impl thread.
149     CCCompletionEvent completion;
150     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::finishAllRenderingOnImplThread, AllowCrossThreadAccess(&completion)));
151     completion.wait();
152 }
153
154 bool CCThreadProxy::isStarted() const
155 {
156     ASSERT(CCProxy::isMainThread());
157     return m_started;
158 }
159
160 bool CCThreadProxy::initializeContext()
161 {
162     TRACE_EVENT("CCThreadProxy::initializeContext", this, 0);
163     RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext();
164     if (!context)
165         return false;
166     ASSERT(context->hasOneRef());
167
168     // Leak the context pointer so we can transfer ownership of it to the other side...
169     GraphicsContext3D* contextPtr = context.release().leakRef();
170     ASSERT(contextPtr->hasOneRef());
171
172     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeContextOnImplThread,
173                                                        AllowCrossThreadAccess(contextPtr)));
174     return true;
175 }
176
177 bool CCThreadProxy::initializeLayerRenderer()
178 {
179     TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0);
180     // Make a blocking call to initializeLayerRendererOnImplThread. The results of that call
181     // are pushed into the initializeSucceeded and capabilities local variables.
182     CCCompletionEvent completion;
183     bool initializeSucceeded = false;
184     LayerRendererCapabilities capabilities;
185     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeLayerRendererOnImplThread,
186                                                        AllowCrossThreadAccess(&completion),
187                                                        AllowCrossThreadAccess(&initializeSucceeded),
188                                                        AllowCrossThreadAccess(&capabilities)));
189     completion.wait();
190
191     if (initializeSucceeded) {
192         m_layerRendererInitialized = true;
193         m_layerRendererCapabilitiesMainThreadCopy = capabilities;
194     }
195     return initializeSucceeded;
196 }
197
198 bool CCThreadProxy::recreateContext()
199 {
200     TRACE_EVENT0("cc", "CCThreadProxy::recreateContext");
201     ASSERT(isMainThread());
202
203     // Try to create the context.
204     RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext();
205     if (!context)
206         return false;
207     ASSERT(context->hasOneRef());
208
209     // Leak the context pointer so we can transfer ownership of it to the other side...
210     GraphicsContext3D* contextPtr = context.release().leakRef();
211     ASSERT(contextPtr->hasOneRef());
212
213     // Make a blocking call to recreateContextOnImplThread. The results of that
214     // call are pushed into the recreateSucceeded and capabilities local
215     // variables.
216     CCCompletionEvent completion;
217     bool recreateSucceeded = false;
218     LayerRendererCapabilities capabilities;
219     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::recreateContextOnImplThread,
220                                                        AllowCrossThreadAccess(&completion),
221                                                        AllowCrossThreadAccess(contextPtr),
222                                                        AllowCrossThreadAccess(&recreateSucceeded),
223                                                        AllowCrossThreadAccess(&capabilities)));
224     completion.wait();
225
226     if (recreateSucceeded)
227         m_layerRendererCapabilitiesMainThreadCopy = capabilities;
228     return recreateSucceeded;
229 }
230
231 int CCThreadProxy::compositorIdentifier() const
232 {
233     ASSERT(isMainThread());
234     return m_compositorIdentifier;
235 }
236
237 const LayerRendererCapabilities& CCThreadProxy::layerRendererCapabilities() const
238 {
239     ASSERT(m_layerRendererInitialized);
240     return m_layerRendererCapabilitiesMainThreadCopy;
241 }
242
243 void CCThreadProxy::loseContext()
244 {
245     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::didLoseContextOnImplThread));
246 }
247
248 void CCThreadProxy::setNeedsAnimate()
249 {
250     ASSERT(isMainThread());
251     if (m_animateRequested)
252         return;
253
254     TRACE_EVENT("CCThreadProxy::setNeedsAnimate", this, 0);
255     m_animateRequested = true;
256     setNeedsCommit();
257 }
258
259 void CCThreadProxy::setNeedsCommit()
260 {
261     ASSERT(isMainThread());
262     if (m_commitRequested)
263         return;
264
265     TRACE_EVENT("CCThreadProxy::setNeedsCommit", this, 0);
266     m_commitRequested = true;
267     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread));
268 }
269
270 void CCThreadProxy::didLoseContextOnImplThread()
271 {
272     ASSERT(isImplThread());
273     TRACE_EVENT0("cc", "CCThreadProxy::didLoseContextOnImplThread");
274     m_schedulerOnImplThread->didLoseContext();
275 }
276
277 void CCThreadProxy::onSwapBuffersCompleteOnImplThread()
278 {
279     ASSERT(isImplThread());
280     TRACE_EVENT("CCThreadProxy::onSwapBuffersCompleteOnImplThread", this, 0);
281     m_schedulerOnImplThread->didSwapBuffersComplete();
282     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCompleteSwapBuffers));
283 }
284
285 void CCThreadProxy::setNeedsCommitOnImplThread()
286 {
287     ASSERT(isImplThread());
288     TRACE_EVENT("CCThreadProxy::setNeedsCommitOnImplThread", this, 0);
289     m_schedulerOnImplThread->setNeedsCommit();
290 }
291
292 void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
293 {
294     ASSERT(isImplThread());
295     TRACE_EVENT("CCThreadProxy::postAnimationEventsToMainThreadOnImplThread", this, 0);
296     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events, wallClockTime));
297 }
298
299 void CCThreadProxy::setNeedsRedraw()
300 {
301     ASSERT(isMainThread());
302     TRACE_EVENT("CCThreadProxy::setNeedsRedraw", this, 0);
303     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFullRootLayerDamageOnImplThread));
304     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread));
305 }
306
307 void CCThreadProxy::setVisible(bool visible)
308 {
309     ASSERT(isMainThread());
310     CCCompletionEvent completion;
311     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setVisibleOnImplThread, AllowCrossThreadAccess(&completion), visible));
312     completion.wait();
313 }
314
315 void CCThreadProxy::setVisibleOnImplThread(CCCompletionEvent* completion, bool visible)
316 {
317     ASSERT(isImplThread());
318     m_schedulerOnImplThread->setVisible(visible);
319     m_layerTreeHostImpl->setVisible(visible);
320     if (!visible) {
321         m_layerTreeHost->didBecomeInvisibleOnImplThread(m_layerTreeHostImpl.get());
322         // as partial or all the textures may be evicted in didBecomeInvisibleOnImplThread,
323         // schedule a commit which will be executed when it goes to visible again.
324         m_schedulerOnImplThread->setNeedsCommit();
325     } else
326         m_schedulerOnImplThread->setNeedsRedraw();
327     completion->signal();
328 }
329
330 void CCThreadProxy::setNeedsRedrawOnImplThread()
331 {
332     ASSERT(isImplThread());
333     TRACE_EVENT("CCThreadProxy::setNeedsRedrawOnImplThread", this, 0);
334     m_schedulerOnImplThread->setNeedsRedraw();
335 }
336
337 void CCThreadProxy::start()
338 {
339     ASSERT(isMainThread());
340     ASSERT(CCProxy::implThread());
341     // Create LayerTreeHostImpl.
342     CCCompletionEvent completion;
343     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeImplOnImplThread, AllowCrossThreadAccess(&completion)));
344     completion.wait();
345
346     m_started = true;
347 }
348
349 void CCThreadProxy::stop()
350 {
351     TRACE_EVENT("CCThreadProxy::stop", this, 0);
352     ASSERT(isMainThread());
353     ASSERT(m_started);
354
355     // Synchronously deletes the impl.
356     CCCompletionEvent completion;
357     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::layerTreeHostClosedOnImplThread, AllowCrossThreadAccess(&completion)));
358     completion.wait();
359
360     m_mainThreadProxy->shutdown(); // Stop running tasks posted to us.
361
362     ASSERT(!m_layerTreeHostImpl); // verify that the impl deleted.
363     m_layerTreeHost = 0;
364     m_started = false;
365 }
366
367 void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion)
368 {
369     TRACE_EVENT("CCThreadProxy::finishAllRenderingOnImplThread", this, 0);
370     ASSERT(isImplThread());
371     ASSERT(!m_finishAllRenderingCompletionEventOnImplThread);
372     m_finishAllRenderingCompletionEventOnImplThread = completion;
373
374     m_schedulerOnImplThread->setNeedsForcedRedraw();
375 }
376
377 void CCThreadProxy::forceBeginFrameOnImplThread(CCCompletionEvent* completion)
378 {
379     TRACE_EVENT0("cc", "CCThreadProxy::forceBeginFrameOnImplThread");
380     ASSERT(!m_beginFrameCompletionEventOnImplThread);
381
382     if (m_schedulerOnImplThread->commitPending()) {
383         completion->signal();
384         return;
385     }
386
387     m_beginFrameCompletionEventOnImplThread = completion;
388     m_schedulerOnImplThread->setNeedsCommit();
389     m_schedulerOnImplThread->setNeedsForcedCommit();
390 }
391
392 void CCThreadProxy::scheduledActionBeginFrame()
393 {
394     TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame");
395     ASSERT(!m_pendingBeginFrameRequest);
396     m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState());
397     m_pendingBeginFrameRequest->frameBeginTime = 0;
398     m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
399
400     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame));
401
402     if (m_beginFrameCompletionEventOnImplThread) {
403         m_beginFrameCompletionEventOnImplThread->signal();
404         m_beginFrameCompletionEventOnImplThread = 0;
405     }
406 }
407
408 void CCThreadProxy::beginFrame()
409 {
410     TRACE_EVENT0("cc", "CCThreadProxy::beginFrame");
411     ASSERT(isMainThread());
412     if (!m_layerTreeHost)
413         return;
414
415     if (!m_pendingBeginFrameRequest) {
416         TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage");
417         return;
418     }
419
420     OwnPtr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.release());
421
422     // Do not notify the impl thread of commit requests that occur during
423     // the apply/animate/layout part of the beginFrameAndCommit process since
424     // those commit requests will get painted immediately. Once we have done
425     // the paint, m_commitRequested will be set to false to allow new commit
426     // requests to be scheduled.
427     m_commitRequested = true;
428
429     // On the other hand, the animationRequested flag needs to be cleared
430     // here so that any animation requests generated by the apply or animate
431     // callbacks will trigger another frame.
432     m_animateRequested = false;
433
434     // FIXME: technically, scroll deltas need to be applied for dropped commits as well.
435     // Re-do the commit flow so that we don't send the scrollInfo on the BFAC message.
436     m_layerTreeHost->applyScrollAndScale(*request->scrollInfo);
437
438     // FIXME: recreate the context if it was requested by the impl thread.
439     m_layerTreeHost->updateAnimations(request->frameBeginTime);
440     m_layerTreeHost->layout();
441
442     // Clear the commit flag after updating animations and layout here --- objects that only
443     // layout when painted will trigger another setNeedsCommit inside
444     // updateLayers.
445     m_commitRequested = false;
446
447     if (!m_layerTreeHost->updateLayers())
448         return;
449
450     // Before applying scrolls and calling animate, we set m_animateRequested to false.
451     // If it is true now, it means setNeedAnimate was called again. Call setNeedsCommit
452     // now so that we get begin frame when this one is done.
453     if (m_animateRequested)
454         setNeedsCommit();
455
456     // Notify the impl thread that the beginFrame has completed. This will
457     // begin the commit process, which is blocking from the main thread's
458     // point of view, but asynchronously performed on the impl thread,
459     // coordinated by the CCScheduler.
460     {
461         TRACE_EVENT("commit", this, 0);
462         CCCompletionEvent completion;
463         CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameCompleteOnImplThread, AllowCrossThreadAccess(&completion)));
464         completion.wait();
465     }
466
467     m_layerTreeHost->commitComplete();
468 }
469
470 void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion)
471 {
472     TRACE_EVENT("CCThreadProxy::beginFrameCompleteOnImplThread", this, 0);
473     ASSERT(!m_commitCompletionEventOnImplThread);
474     ASSERT(isImplThread());
475     ASSERT(m_schedulerOnImplThread);
476     ASSERT(m_schedulerOnImplThread->commitPending());
477     if (!m_layerTreeHostImpl) {
478         completion->signal();
479         return;
480     }
481
482     m_commitCompletionEventOnImplThread = completion;
483
484     ASSERT(!m_currentTextureUpdaterOnImplThread);
485     m_currentTextureUpdaterOnImplThread = adoptPtr(new CCTextureUpdater(m_layerTreeHostImpl->contentsTextureAllocator()));
486     m_layerTreeHost->updateCompositorResources(m_layerTreeHostImpl->context(), *m_currentTextureUpdaterOnImplThread);
487
488     m_schedulerOnImplThread->beginFrameComplete();
489 }
490
491 bool CCThreadProxy::hasMoreResourceUpdates() const
492 {
493     if (!m_currentTextureUpdaterOnImplThread)
494         return false;
495     return m_currentTextureUpdaterOnImplThread->hasMoreUpdates();
496 }
497
498 bool CCThreadProxy::canDraw()
499 {
500     ASSERT(isImplThread());
501     if (!m_layerTreeHostImpl)
502         return false;
503     return m_layerTreeHostImpl->canDraw();
504 }
505
506 void CCThreadProxy::scheduledActionUpdateMoreResources()
507 {
508     TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0);
509     ASSERT(m_currentTextureUpdaterOnImplThread);
510     m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame);
511 }
512
513 void CCThreadProxy::scheduledActionCommit()
514 {
515     TRACE_EVENT("CCThreadProxy::scheduledActionCommit", this, 0);
516     ASSERT(m_currentTextureUpdaterOnImplThread);
517     ASSERT(!m_currentTextureUpdaterOnImplThread->hasMoreUpdates());
518     ASSERT(m_commitCompletionEventOnImplThread);
519
520     m_currentTextureUpdaterOnImplThread.clear();
521
522
523     m_layerTreeHostImpl->beginCommit();
524
525     m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
526     m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
527
528     m_layerTreeHostImpl->commitComplete();
529
530     m_nextFrameIsNewlyCommittedFrameOnImplThread = true;
531
532     m_commitCompletionEventOnImplThread->signal();
533     m_commitCompletionEventOnImplThread = 0;
534 }
535
536 void CCThreadProxy::scheduledActionBeginContextRecreation()
537 {
538     ASSERT(isImplThread());
539     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation));
540 }
541
542 void CCThreadProxy::scheduledActionDrawAndSwap()
543 {
544     TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0);
545     ASSERT(isImplThread());
546     if (!m_layerTreeHostImpl)
547         return;
548
549     // FIXME: compute the frame display time more intelligently
550     double monotonicTime = monotonicallyIncreasingTime();
551     double wallClockTime = currentTime();
552
553     m_inputHandlerOnImplThread->animate(monotonicTime);
554     m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
555     m_layerTreeHostImpl->drawLayers();
556
557     // Check for a pending compositeAndReadback.
558     if (m_readbackRequestOnImplThread) {
559         m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect);
560         m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost();
561         m_readbackRequestOnImplThread->completion.signal();
562         m_readbackRequestOnImplThread = 0;
563     }
564
565     m_layerTreeHostImpl->swapBuffers();
566
567     // Process any finish request
568     if (m_finishAllRenderingCompletionEventOnImplThread) {
569         m_layerTreeHostImpl->finishAllRendering();
570         m_finishAllRenderingCompletionEventOnImplThread->signal();
571         m_finishAllRenderingCompletionEventOnImplThread = 0;
572     }
573
574     // Tell the main thread that the the newly-commited frame was drawn.
575     if (m_nextFrameIsNewlyCommittedFrameOnImplThread) {
576         m_nextFrameIsNewlyCommittedFrameOnImplThread = false;
577         m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame));
578     }
579 }
580
581 void CCThreadProxy::didCommitAndDrawFrame()
582 {
583     ASSERT(isMainThread());
584     if (!m_layerTreeHost)
585         return;
586     m_layerTreeHost->didCommitAndDrawFrame();
587 }
588
589 void CCThreadProxy::didCompleteSwapBuffers()
590 {
591     ASSERT(isMainThread());
592     if (!m_layerTreeHost)
593         return;
594     m_layerTreeHost->didCompleteSwapBuffers();
595 }
596
597 void CCThreadProxy::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
598 {
599     TRACE_EVENT0("cc", "CCThreadProxy::setAnimationEvents");
600     ASSERT(isMainThread());
601     if (!m_layerTreeHost)
602         return;
603     m_layerTreeHost->setAnimationEvents(events, wallClockTime);
604 }
605
606 class CCThreadProxyContextRecreationTimer : public CCTimer, CCTimerClient {
607 public:
608     static PassOwnPtr<CCThreadProxyContextRecreationTimer> create(CCThreadProxy* proxy) { return adoptPtr(new CCThreadProxyContextRecreationTimer(proxy)); }
609
610     virtual void onTimerFired()
611     {
612         m_proxy->tryToRecreateContext();
613     }
614
615     enum Recreation { RecreationTickRateMs = 30 };
616
617 private:
618     explicit CCThreadProxyContextRecreationTimer(CCThreadProxy* proxy)
619         : CCTimer(CCProxy::mainThread(), this)
620         , m_proxy(proxy)
621     {
622     }
623
624     CCThreadProxy* m_proxy;
625 };
626
627 void CCThreadProxy::beginContextRecreation()
628 {
629     TRACE_EVENT0("cc", "CCThreadProxy::beginContextRecreation");
630     ASSERT(isMainThread());
631     ASSERT(!m_contextRecreationTimer);
632     m_contextRecreationTimer = CCThreadProxyContextRecreationTimer::create(this);
633     m_layerTreeHost->didLoseContext();
634     m_contextRecreationTimer->startOneShot(CCThreadProxyContextRecreationTimer::RecreationTickRateMs);
635 }
636
637 void CCThreadProxy::tryToRecreateContext()
638 {
639     ASSERT(isMainThread());
640     ASSERT(m_layerTreeHost);
641     CCLayerTreeHost::RecreateResult result = m_layerTreeHost->recreateContext();
642     if (result == CCLayerTreeHost::RecreateFailedButTryAgain)
643         m_contextRecreationTimer->startOneShot(CCThreadProxyContextRecreationTimer::RecreationTickRateMs);
644     else if (result == CCLayerTreeHost::RecreateSucceeded)
645         m_contextRecreationTimer.clear();
646 }
647
648 void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion)
649 {
650     TRACE_EVENT("CCThreadProxy::initializeImplOnImplThread", this, 0);
651     ASSERT(isImplThread());
652     m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
653     const double displayRefreshIntervalMs = 1000.0 / 60.0;
654     OwnPtr<CCFrameRateController> frameRateController = adoptPtr(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshIntervalMs, CCProxy::implThread())));
655     m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.release());
656     m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible());
657
658     m_inputHandlerOnImplThread = CCInputHandler::create(m_layerTreeHostImpl.get());
659     m_compositorIdentifier = m_inputHandlerOnImplThread->identifier();
660
661     completion->signal();
662 }
663
664 void CCThreadProxy::initializeContextOnImplThread(GraphicsContext3D* context)
665 {
666     TRACE_EVENT("CCThreadProxy::initializeContextOnImplThread", this, 0);
667     ASSERT(isImplThread());
668     m_contextBeforeInitializationOnImplThread = adoptRef(context);
669 }
670
671 void CCThreadProxy::initializeLayerRendererOnImplThread(CCCompletionEvent* completion, bool* initializeSucceeded, LayerRendererCapabilities* capabilities)
672 {
673     TRACE_EVENT("CCThreadProxy::initializeLayerRendererOnImplThread", this, 0);
674     ASSERT(isImplThread());
675     ASSERT(m_contextBeforeInitializationOnImplThread);
676     *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitializationOnImplThread.release());
677     if (*initializeSucceeded) {
678         *capabilities = m_layerTreeHostImpl->layerRendererCapabilities();
679         if (capabilities->usingSwapCompleteCallback)
680             m_schedulerOnImplThread->setMaxFramesPending(2);
681     }
682
683     completion->signal();
684 }
685
686 void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completion)
687 {
688     TRACE_EVENT("CCThreadProxy::layerTreeHostClosedOnImplThread", this, 0);
689     ASSERT(isImplThread());
690     m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
691     m_layerTreeHostImpl.clear();
692     m_inputHandlerOnImplThread.clear();
693     m_schedulerOnImplThread.clear();
694     completion->signal();
695 }
696
697 void CCThreadProxy::setFullRootLayerDamageOnImplThread()
698 {
699     ASSERT(isImplThread());
700     m_layerTreeHostImpl->setFullRootLayerDamage();
701 }
702
703 size_t CCThreadProxy::maxPartialTextureUpdates() const
704 {
705     return textureUpdatesPerFrame;
706 }
707
708 void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, GraphicsContext3D* contextPtr, bool* recreateSucceeded, LayerRendererCapabilities* capabilities)
709 {
710     TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread");
711     ASSERT(isImplThread());
712     m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
713     *recreateSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(adoptRef(contextPtr));
714     if (*recreateSucceeded) {
715         *capabilities = m_layerTreeHostImpl->layerRendererCapabilities();
716         m_schedulerOnImplThread->didRecreateContext();
717     }
718     completion->signal();
719 }
720
721 } // namespace WebCore