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