a9bfbc1a78aaed936248304184808dfcbb59fffd
[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 "SharedGraphicsContext3D.h"
31 #include "TraceEvent.h"
32 #include "cc/CCDelayBasedTimeSource.h"
33 #include "cc/CCDrawQuad.h"
34 #include "cc/CCFontAtlas.h"
35 #include "cc/CCFrameRateController.h"
36 #include "cc/CCGraphicsContext.h"
37 #include "cc/CCInputHandler.h"
38 #include "cc/CCLayerTreeHost.h"
39 #include "cc/CCScheduler.h"
40 #include "cc/CCScopedThreadProxy.h"
41 #include "cc/CCTextureUpdater.h"
42 #include "cc/CCThreadTask.h"
43 #include <wtf/CurrentTime.h>
44 #include <wtf/MainThread.h>
45
46 using namespace WTF;
47
48 namespace {
49
50 // Number of textures to update with each call to
51 // scheduledActionUpdateMoreResources().
52 static const size_t textureUpdatesPerFrame = 48;
53
54 // Measured in seconds.
55 static const double contextRecreationTickRate = 0.03;
56
57 } // anonymous namespace
58
59 namespace WebCore {
60
61 namespace {
62
63 // Type of texture uploader to use for texture updates.
64 static TextureUploaderOption textureUploader = ThrottledUploader;
65
66 } // anonymous namespace
67
68 PassOwnPtr<CCProxy> CCThreadProxy::create(CCLayerTreeHost* layerTreeHost)
69 {
70     return adoptPtr(new CCThreadProxy(layerTreeHost));
71 }
72
73 CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost)
74     : m_animateRequested(false)
75     , m_commitRequested(false)
76     , m_forcedCommitRequested(false)
77     , m_contextLost(false)
78     , m_layerTreeHost(layerTreeHost)
79     , m_compositorIdentifier(-1)
80     , m_layerRendererInitialized(false)
81     , m_started(false)
82     , m_texturesAcquired(true)
83     , m_mainThreadProxy(CCScopedThreadProxy::create(CCProxy::mainThread()))
84     , m_beginFrameCompletionEventOnImplThread(0)
85     , m_readbackRequestOnImplThread(0)
86     , m_commitCompletionEventOnImplThread(0)
87     , m_textureAcquisitionCompletionEventOnImplThread(0)
88     , m_nextFrameIsNewlyCommittedFrameOnImplThread(false)
89 {
90     TRACE_EVENT("CCThreadProxy::CCThreadProxy", this, 0);
91     ASSERT(isMainThread());
92 }
93
94 CCThreadProxy::~CCThreadProxy()
95 {
96     TRACE_EVENT("CCThreadProxy::~CCThreadProxy", this, 0);
97     ASSERT(isMainThread());
98     ASSERT(!m_started);
99 }
100
101 bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
102 {
103     TRACE_EVENT("CCThreadPRoxy::compositeAndReadback", this, 0);
104     ASSERT(isMainThread());
105     ASSERT(m_layerTreeHost);
106
107     if (!m_layerTreeHost->initializeLayerRendererIfNeeded()) {
108         TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0);
109         return false;
110     }
111
112
113     // Perform a synchronous commit.
114     CCCompletionEvent beginFrameCompletion;
115     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceBeginFrameOnImplThread, AllowCrossThreadAccess(&beginFrameCompletion)));
116     beginFrameCompletion.wait();
117     beginFrame();
118
119     // Perform a synchronous readback.
120     ReadbackRequest request;
121     request.rect = rect;
122     request.pixels = pixels;
123     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestReadbackOnImplThread, AllowCrossThreadAccess(&request)));
124     request.completion.wait();
125     return request.success;
126 }
127
128 void CCThreadProxy::requestReadbackOnImplThread(ReadbackRequest* request)
129 {
130     ASSERT(CCProxy::isImplThread());
131     ASSERT(!m_readbackRequestOnImplThread);
132     if (!m_layerTreeHostImpl) {
133         request->success = false;
134         request->completion.signal();
135         return;
136     }
137
138     m_readbackRequestOnImplThread = request;
139     m_schedulerOnImplThread->setNeedsRedraw();
140     m_schedulerOnImplThread->setNeedsForcedRedraw();
141 }
142
143 void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration)
144 {
145     ASSERT(CCProxy::isMainThread());
146     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, duration));
147 }
148
149 void CCThreadProxy::requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double duration)
150 {
151     ASSERT(CCProxy::isImplThread());
152     if (m_layerTreeHostImpl)
153         m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration);
154 }
155
156 CCGraphicsContext* CCThreadProxy::context()
157 {
158     return 0;
159 }
160
161 void CCThreadProxy::finishAllRendering()
162 {
163     ASSERT(CCProxy::isMainThread());
164
165     // Make sure all GL drawing is finished on the impl thread.
166     CCCompletionEvent completion;
167     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::finishAllRenderingOnImplThread, AllowCrossThreadAccess(&completion)));
168     completion.wait();
169 }
170
171 bool CCThreadProxy::isStarted() const
172 {
173     ASSERT(CCProxy::isMainThread());
174     return m_started;
175 }
176
177 bool CCThreadProxy::initializeContext()
178 {
179     TRACE_EVENT("CCThreadProxy::initializeContext", this, 0);
180     RefPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
181     if (!context)
182         return false;
183     ASSERT(context->hasOneRef());
184
185     // Leak the context pointer so we can transfer ownership of it to the other side...
186     CCGraphicsContext* contextPtr = context.release().leakRef();
187     ASSERT(contextPtr->hasOneRef());
188
189     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeContextOnImplThread,
190                                                        AllowCrossThreadAccess(contextPtr)));
191     return true;
192 }
193
194 void CCThreadProxy::setSurfaceReady()
195 {
196     TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReady");
197     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setSurfaceReadyOnImplThread));
198 }
199
200 void CCThreadProxy::setSurfaceReadyOnImplThread()
201 {
202     TRACE_EVENT0("cc", "CCThreadProxy::setSurfaceReadyOnImplThread");
203     m_schedulerOnImplThread->setCanBeginFrame(true);
204 }
205
206 bool CCThreadProxy::initializeLayerRenderer()
207 {
208     TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0);
209     // Make a blocking call to initializeLayerRendererOnImplThread. The results of that call
210     // are pushed into the initializeSucceeded and capabilities local variables.
211     CCCompletionEvent completion;
212     bool initializeSucceeded = false;
213     LayerRendererCapabilities capabilities;
214     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeLayerRendererOnImplThread,
215                                                        AllowCrossThreadAccess(&completion),
216                                                        AllowCrossThreadAccess(&initializeSucceeded),
217                                                        AllowCrossThreadAccess(&capabilities)));
218     completion.wait();
219
220     if (initializeSucceeded) {
221         m_layerRendererInitialized = true;
222         m_layerRendererCapabilitiesMainThreadCopy = capabilities;
223     }
224     return initializeSucceeded;
225 }
226
227 bool CCThreadProxy::recreateContext()
228 {
229     TRACE_EVENT0("cc", "CCThreadProxy::recreateContext");
230     ASSERT(isMainThread());
231
232     // Try to create the context.
233     RefPtr<CCGraphicsContext> context = m_layerTreeHost->createContext();
234     if (!context)
235         return false;
236     if (CCLayerTreeHost::needsFilterContext() && !m_layerTreeHost->settings().forceSoftwareCompositing)
237         if (!SharedGraphicsContext3D::createForImplThread())
238             return false;
239
240     ASSERT(context->hasOneRef());
241
242     // Leak the context pointer so we can transfer ownership of it to the other side...
243     CCGraphicsContext* contextPtr = context.release().leakRef();
244     ASSERT(contextPtr->hasOneRef());
245
246     // Make a blocking call to recreateContextOnImplThread. The results of that
247     // call are pushed into the recreateSucceeded and capabilities local
248     // variables.
249     CCCompletionEvent completion;
250     bool recreateSucceeded = false;
251     LayerRendererCapabilities capabilities;
252     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::recreateContextOnImplThread,
253                                                        AllowCrossThreadAccess(&completion),
254                                                        AllowCrossThreadAccess(contextPtr),
255                                                        AllowCrossThreadAccess(&recreateSucceeded),
256                                                        AllowCrossThreadAccess(&capabilities)));
257     completion.wait();
258
259     if (recreateSucceeded)
260         m_layerRendererCapabilitiesMainThreadCopy = capabilities;
261     return recreateSucceeded;
262 }
263
264 int CCThreadProxy::compositorIdentifier() const
265 {
266     ASSERT(isMainThread());
267     return m_compositorIdentifier;
268 }
269
270 const LayerRendererCapabilities& CCThreadProxy::layerRendererCapabilities() const
271 {
272     ASSERT(m_layerRendererInitialized);
273     return m_layerRendererCapabilitiesMainThreadCopy;
274 }
275
276 void CCThreadProxy::loseContext()
277 {
278     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::didLoseContextOnImplThread));
279 }
280
281 void CCThreadProxy::setNeedsAnimate()
282 {
283     ASSERT(isMainThread());
284     if (m_animateRequested)
285         return;
286
287     TRACE_EVENT("CCThreadProxy::setNeedsAnimate", this, 0);
288     m_animateRequested = true;
289     setNeedsCommit();
290 }
291
292 void CCThreadProxy::setNeedsCommit()
293 {
294     ASSERT(isMainThread());
295     if (m_commitRequested)
296         return;
297
298     TRACE_EVENT("CCThreadProxy::setNeedsCommit", this, 0);
299     m_commitRequested = true;
300     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread));
301 }
302
303 void CCThreadProxy::setNeedsForcedCommit()
304 {
305     ASSERT(isMainThread());
306     if (m_forcedCommitRequested)
307         return;
308
309     TRACE_EVENT("CCThreadProxy::setNeedsForcedCommit", this, 0);
310     m_commitRequested = true;
311     m_forcedCommitRequested = true;
312     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsForcedCommitOnImplThread));
313 }
314
315 void CCThreadProxy::didLoseContextOnImplThread()
316 {
317     ASSERT(isImplThread());
318     TRACE_EVENT0("cc", "CCThreadProxy::didLoseContextOnImplThread");
319     m_schedulerOnImplThread->didLoseContext();
320 }
321
322 void CCThreadProxy::onSwapBuffersCompleteOnImplThread()
323 {
324     ASSERT(isImplThread());
325     TRACE_EVENT("CCThreadProxy::onSwapBuffersCompleteOnImplThread", this, 0);
326     m_schedulerOnImplThread->didSwapBuffersComplete();
327     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCompleteSwapBuffers));
328 }
329
330 void CCThreadProxy::setNeedsCommitOnImplThread()
331 {
332     ASSERT(isImplThread());
333     TRACE_EVENT("CCThreadProxy::setNeedsCommitOnImplThread", this, 0);
334     m_schedulerOnImplThread->setNeedsCommit();
335 }
336
337 void CCThreadProxy::setNeedsForcedCommitOnImplThread()
338 {
339     ASSERT(isImplThread());
340     TRACE_EVENT("CCThreadProxy::setNeedsForcedCommitOnImplThread", this, 0);
341     m_schedulerOnImplThread->setNeedsCommit();
342     m_schedulerOnImplThread->setNeedsForcedCommit();
343 }
344
345 void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
346 {
347     ASSERT(isImplThread());
348     TRACE_EVENT("CCThreadProxy::postAnimationEventsToMainThreadOnImplThread", this, 0);
349     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events, wallClockTime));
350 }
351
352 void CCThreadProxy::postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t bytes)
353 {
354     ASSERT(isImplThread());
355     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setContentsMemoryAllocationLimitBytes, bytes));
356 }
357
358 void CCThreadProxy::setNeedsRedraw()
359 {
360     ASSERT(isMainThread());
361     TRACE_EVENT("CCThreadProxy::setNeedsRedraw", this, 0);
362     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFullRootLayerDamageOnImplThread));
363     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnImplThread));
364 }
365
366 bool CCThreadProxy::commitRequested() const
367 {
368     ASSERT(isMainThread());
369     return m_commitRequested;
370 }
371
372 void CCThreadProxy::setNeedsRedrawOnImplThread()
373 {
374     ASSERT(isImplThread());
375     TRACE_EVENT("CCThreadProxy::setNeedsRedrawOnImplThread", this, 0);
376     m_schedulerOnImplThread->setNeedsRedraw();
377 }
378
379 void CCThreadProxy::start()
380 {
381     ASSERT(isMainThread());
382     ASSERT(CCProxy::implThread());
383     // Create LayerTreeHostImpl.
384     CCCompletionEvent completion;
385     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeImplOnImplThread, AllowCrossThreadAccess(&completion)));
386     completion.wait();
387
388     m_started = true;
389 }
390
391 void CCThreadProxy::stop()
392 {
393     TRACE_EVENT("CCThreadProxy::stop", this, 0);
394     ASSERT(isMainThread());
395     ASSERT(m_started);
396
397     // Synchronously deletes the impl.
398     {
399         DebugScopedSetMainThreadBlocked mainThreadBlocked;
400
401         CCCompletionEvent completion;
402         CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::layerTreeHostClosedOnImplThread, AllowCrossThreadAccess(&completion)));
403         completion.wait();
404     }
405
406     m_mainThreadProxy->shutdown(); // Stop running tasks posted to us.
407
408     ASSERT(!m_layerTreeHostImpl); // verify that the impl deleted.
409     m_layerTreeHost = 0;
410     m_started = false;
411 }
412
413 void CCThreadProxy::forceSerializeOnSwapBuffers()
414 {
415     CCCompletionEvent completion;
416     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread, AllowCrossThreadAccess(&completion)));
417     completion.wait();
418 }
419
420 void CCThreadProxy::forceSerializeOnSwapBuffersOnImplThread(CCCompletionEvent* completion)
421 {
422     if (m_layerRendererInitialized)
423         m_layerTreeHostImpl->layerRenderer()->doNoOp();
424     completion->signal();
425 }
426
427
428 void CCThreadProxy::finishAllRenderingOnImplThread(CCCompletionEvent* completion)
429 {
430     TRACE_EVENT("CCThreadProxy::finishAllRenderingOnImplThread", this, 0);
431     ASSERT(isImplThread());
432     m_layerTreeHostImpl->finishAllRendering();
433     completion->signal();
434 }
435
436 void CCThreadProxy::forceBeginFrameOnImplThread(CCCompletionEvent* completion)
437 {
438     TRACE_EVENT0("cc", "CCThreadProxy::forceBeginFrameOnImplThread");
439     ASSERT(!m_beginFrameCompletionEventOnImplThread);
440
441     if (m_schedulerOnImplThread->commitPending()) {
442         completion->signal();
443         return;
444     }
445
446     m_beginFrameCompletionEventOnImplThread = completion;
447     setNeedsForcedCommitOnImplThread();
448 }
449
450 void CCThreadProxy::scheduledActionBeginFrame()
451 {
452     TRACE_EVENT0("cc", "CCThreadProxy::scheduledActionBeginFrame");
453     ASSERT(!m_pendingBeginFrameRequest);
454     m_pendingBeginFrameRequest = adoptPtr(new BeginFrameAndCommitState());
455     m_pendingBeginFrameRequest->monotonicFrameBeginTime = monotonicallyIncreasingTime();
456     m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
457     m_currentTextureUpdaterOnImplThread = adoptPtr(new CCTextureUpdater);
458     m_pendingBeginFrameRequest->updater = m_currentTextureUpdaterOnImplThread.get();
459
460     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrame));
461
462     if (m_beginFrameCompletionEventOnImplThread) {
463         m_beginFrameCompletionEventOnImplThread->signal();
464         m_beginFrameCompletionEventOnImplThread = 0;
465     }
466 }
467
468 void CCThreadProxy::beginFrame()
469 {
470     TRACE_EVENT0("cc", "CCThreadProxy::beginFrame");
471     ASSERT(isMainThread());
472     if (!m_layerTreeHost)
473         return;
474
475     if (!m_pendingBeginFrameRequest) {
476         TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage");
477         return;
478     }
479
480     if (CCLayerTreeHost::needsFilterContext() && !m_layerTreeHost->settings().forceSoftwareCompositing && !SharedGraphicsContext3D::haveForImplThread())
481         SharedGraphicsContext3D::createForImplThread();
482
483     OwnPtr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.release());
484
485     // Do not notify the impl thread of commit requests that occur during
486     // the apply/animate/layout part of the beginFrameAndCommit process since
487     // those commit requests will get painted immediately. Once we have done
488     // the paint, m_commitRequested will be set to false to allow new commit
489     // requests to be scheduled.
490     m_commitRequested = true;
491
492     // On the other hand, the animationRequested flag needs to be cleared
493     // here so that any animation requests generated by the apply or animate
494     // callbacks will trigger another frame.
495     m_animateRequested = false;
496
497     // FIXME: technically, scroll deltas need to be applied for dropped commits as well.
498     // Re-do the commit flow so that we don't send the scrollInfo on the BFAC message.
499     m_layerTreeHost->applyScrollAndScale(*request->scrollInfo);
500
501     m_layerTreeHost->willBeginFrame();
502
503     // FIXME: recreate the context if it was requested by the impl thread.
504     m_layerTreeHost->updateAnimations(request->monotonicFrameBeginTime);
505     m_layerTreeHost->layout();
506
507     // Clear the commit flag after updating animations and layout here --- objects that only
508     // layout when painted will trigger another setNeedsCommit inside
509     // updateLayers.
510     m_commitRequested = false;
511     m_forcedCommitRequested = false;
512
513     if (!m_layerTreeHost->initializeLayerRendererIfNeeded())
514         return;
515
516     m_layerTreeHost->updateLayers(*request->updater);
517
518     // Once single buffered layers are committed, they cannot be modified until
519     // they are drawn by the impl thread.
520     m_texturesAcquired = false;
521
522     m_layerTreeHost->willCommit();
523     // Before applying scrolls and calling animate, we set m_animateRequested to false.
524     // If it is true now, it means setNeedAnimate was called again. Call setNeedsCommit
525     // now so that we get begin frame when this one is done.
526     if (m_animateRequested)
527         setNeedsCommit();
528
529     // Notify the impl thread that the beginFrame has completed. This will
530     // begin the commit process, which is blocking from the main thread's
531     // point of view, but asynchronously performed on the impl thread,
532     // coordinated by the CCScheduler.
533     {
534         TRACE_EVENT("commit", this, 0);
535         DebugScopedSetMainThreadBlocked mainThreadBlocked;
536
537         CCCompletionEvent completion;
538         CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::beginFrameCompleteOnImplThread, AllowCrossThreadAccess(&completion)));
539         completion.wait();
540     }
541
542     m_layerTreeHost->commitComplete();
543     m_layerTreeHost->didBeginFrame();
544 }
545
546 void CCThreadProxy::beginFrameCompleteOnImplThread(CCCompletionEvent* completion)
547 {
548     TRACE_EVENT("CCThreadProxy::beginFrameCompleteOnImplThread", this, 0);
549     ASSERT(!m_commitCompletionEventOnImplThread);
550     ASSERT(isImplThread());
551     ASSERT(m_schedulerOnImplThread);
552     ASSERT(m_schedulerOnImplThread->commitPending());
553
554     if (!m_layerTreeHostImpl) {
555         completion->signal();
556         return;
557     }
558
559     m_commitCompletionEventOnImplThread = completion;
560
561     m_schedulerOnImplThread->beginFrameComplete();
562 }
563
564 bool CCThreadProxy::hasMoreResourceUpdates() const
565 {
566     if (!m_currentTextureUpdaterOnImplThread)
567         return false;
568     return m_currentTextureUpdaterOnImplThread->hasMoreUpdates();
569 }
570
571 bool CCThreadProxy::canDraw()
572 {
573     ASSERT(isImplThread());
574     if (!m_layerTreeHostImpl)
575         return false;
576     return m_layerTreeHostImpl->canDraw();
577 }
578
579 void CCThreadProxy::scheduledActionUpdateMoreResources()
580 {
581     TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0);
582     ASSERT(m_currentTextureUpdaterOnImplThread);
583     m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), m_layerTreeHostImpl->contentsTextureAllocator(), m_layerTreeHostImpl->layerRenderer()->textureCopier(), m_layerTreeHostImpl->layerRenderer()->textureUploader(), textureUpdatesPerFrame);
584 }
585
586 void CCThreadProxy::scheduledActionCommit()
587 {
588     TRACE_EVENT("CCThreadProxy::scheduledActionCommit", this, 0);
589     ASSERT(isImplThread());
590     ASSERT(m_currentTextureUpdaterOnImplThread);
591     ASSERT(!m_currentTextureUpdaterOnImplThread->hasMoreUpdates());
592     ASSERT(m_commitCompletionEventOnImplThread);
593
594     m_currentTextureUpdaterOnImplThread.clear();
595
596     m_layerTreeHostImpl->beginCommit();
597
598     m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
599     m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
600     m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible());
601
602     m_layerTreeHostImpl->commitComplete();
603
604     m_nextFrameIsNewlyCommittedFrameOnImplThread = true;
605
606     m_commitCompletionEventOnImplThread->signal();
607     m_commitCompletionEventOnImplThread = 0;
608 }
609
610 void CCThreadProxy::scheduledActionBeginContextRecreation()
611 {
612     ASSERT(isImplThread());
613     m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation));
614 }
615
616 CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapInternal(bool forcedDraw)
617 {
618     TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0);
619     CCScheduledActionDrawAndSwapResult result;
620     result.didDraw = false;
621     result.didSwap = false;
622     ASSERT(isImplThread());
623     ASSERT(m_layerTreeHostImpl);
624     if (!m_layerTreeHostImpl)
625         return result;
626
627     ASSERT(m_layerTreeHostImpl->layerRenderer());
628     if (!m_layerTreeHostImpl->layerRenderer())
629         return result;
630
631     // FIXME: compute the frame display time more intelligently
632     double monotonicTime = monotonicallyIncreasingTime();
633     double wallClockTime = currentTime();
634
635     m_inputHandlerOnImplThread->animate(monotonicTime);
636     m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
637
638     // This method is called on a forced draw, regardless of whether we are able to produce a frame,
639     // as the calling site on main thread is blocked until its request completes, and we signal
640     // completion here. If canDraw() is false, we will indicate success=false to the caller, but we
641     // must still signal completion to avoid deadlock.
642
643     // We guard prepareToDraw() with canDraw() because it always returns a valid frame, so can only
644     // be used when such a frame is possible. Since drawLayers() depends on the result of
645     // prepareToDraw(), it is guarded on canDraw() as well.
646
647     CCLayerTreeHostImpl::FrameData frame;
648     bool drawFrame = m_layerTreeHostImpl->canDraw() && (m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw);
649     if (drawFrame) {
650         m_layerTreeHostImpl->drawLayers(frame);
651         result.didDraw = true;
652     }
653     m_layerTreeHostImpl->didDrawAllLayers(frame);
654
655     // Check for a pending compositeAndReadback.
656     if (m_readbackRequestOnImplThread) {
657         m_readbackRequestOnImplThread->success = false;
658         if (drawFrame) {
659             m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect);
660             m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost();
661         }
662         m_readbackRequestOnImplThread->completion.signal();
663         m_readbackRequestOnImplThread = 0;
664     }
665
666     if (drawFrame)
667         result.didSwap = m_layerTreeHostImpl->swapBuffers();
668
669     // Tell the main thread that the the newly-commited frame was drawn.
670     if (m_nextFrameIsNewlyCommittedFrameOnImplThread) {
671         m_nextFrameIsNewlyCommittedFrameOnImplThread = false;
672         m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame));
673     }
674
675     return result;
676 }
677
678 void CCThreadProxy::acquireLayerTextures()
679 {
680     // Called when the main thread needs to modify a layer texture that is used
681     // directly by the compositor.
682     // This method will block until the next compositor draw if there is a
683     // previously committed frame that is still undrawn. This is necessary to
684     // ensure that the main thread does not monopolize access to the textures.
685     ASSERT(isMainThread());
686
687     if (m_texturesAcquired)
688         return;
689
690     TRACE_EVENT("CCThreadProxy::acquireLayerTextures", this, 0);
691     CCCompletionEvent completion;
692     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread, AllowCrossThreadAccess(&completion)));
693     completion.wait(); // Block until it is safe to write to layer textures from the main thread.
694
695     m_texturesAcquired = true;
696 }
697
698 void CCThreadProxy::acquireLayerTexturesForMainThreadOnImplThread(CCCompletionEvent* completion)
699 {
700     ASSERT(isImplThread());
701     ASSERT(!m_textureAcquisitionCompletionEventOnImplThread);
702
703     m_textureAcquisitionCompletionEventOnImplThread = completion;
704     m_schedulerOnImplThread->setMainThreadNeedsLayerTextures();
705 }
706
707 void CCThreadProxy::scheduledActionAcquireLayerTexturesForMainThread()
708 {
709     ASSERT(m_textureAcquisitionCompletionEventOnImplThread);
710     m_textureAcquisitionCompletionEventOnImplThread->signal();
711     m_textureAcquisitionCompletionEventOnImplThread = 0;
712 }
713
714 CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapIfPossible()
715 {
716     return scheduledActionDrawAndSwapInternal(false);
717 }
718
719 CCScheduledActionDrawAndSwapResult CCThreadProxy::scheduledActionDrawAndSwapForced()
720 {
721     return scheduledActionDrawAndSwapInternal(true);
722 }
723
724 void CCThreadProxy::didCommitAndDrawFrame()
725 {
726     ASSERT(isMainThread());
727     if (!m_layerTreeHost)
728         return;
729     m_layerTreeHost->didCommitAndDrawFrame();
730 }
731
732 void CCThreadProxy::didCompleteSwapBuffers()
733 {
734     ASSERT(isMainThread());
735     if (!m_layerTreeHost)
736         return;
737     m_layerTreeHost->didCompleteSwapBuffers();
738 }
739
740 void CCThreadProxy::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime)
741 {
742     TRACE_EVENT0("cc", "CCThreadProxy::setAnimationEvents");
743     ASSERT(isMainThread());
744     if (!m_layerTreeHost)
745         return;
746     m_layerTreeHost->setAnimationEvents(events, wallClockTime);
747 }
748
749 void CCThreadProxy::setContentsMemoryAllocationLimitBytes(size_t bytes)
750 {
751     ASSERT(isMainThread());
752     if (!m_layerTreeHost)
753         return;
754     m_layerTreeHost->setContentsMemoryAllocationLimitBytes(bytes);
755 }
756
757 class CCThreadProxyContextRecreationTimer : public CCTimer, CCTimerClient {
758 public:
759     static PassOwnPtr<CCThreadProxyContextRecreationTimer> create(CCThreadProxy* proxy) { return adoptPtr(new CCThreadProxyContextRecreationTimer(proxy)); }
760
761     virtual void onTimerFired() OVERRIDE
762     {
763         m_proxy->tryToRecreateContext();
764     }
765
766 private:
767     explicit CCThreadProxyContextRecreationTimer(CCThreadProxy* proxy)
768         : CCTimer(CCProxy::mainThread(), this)
769         , m_proxy(proxy)
770     {
771     }
772
773     CCThreadProxy* m_proxy;
774 };
775
776 void CCThreadProxy::beginContextRecreation()
777 {
778     TRACE_EVENT0("cc", "CCThreadProxy::beginContextRecreation");
779     ASSERT(isMainThread());
780     ASSERT(!m_contextRecreationTimer);
781     m_contextRecreationTimer = CCThreadProxyContextRecreationTimer::create(this);
782     m_layerTreeHost->didLoseContext();
783     m_contextRecreationTimer->startOneShot(contextRecreationTickRate);
784 }
785
786 void CCThreadProxy::tryToRecreateContext()
787 {
788     ASSERT(isMainThread());
789     ASSERT(m_layerTreeHost);
790     CCLayerTreeHost::RecreateResult result = m_layerTreeHost->recreateContext();
791     if (result == CCLayerTreeHost::RecreateFailedButTryAgain)
792         m_contextRecreationTimer->startOneShot(contextRecreationTickRate);
793     else if (result == CCLayerTreeHost::RecreateSucceeded)
794         m_contextRecreationTimer.clear();
795 }
796
797 void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion)
798 {
799     TRACE_EVENT("CCThreadProxy::initializeImplOnImplThread", this, 0);
800     ASSERT(isImplThread());
801     m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl(this);
802     const double displayRefreshInterval = 1.0 / 60.0;
803     OwnPtr<CCFrameRateController> frameRateController = adoptPtr(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshInterval, CCProxy::implThread())));
804     m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.release());
805     m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible());
806
807     m_inputHandlerOnImplThread = CCInputHandler::create(m_layerTreeHostImpl.get());
808     m_compositorIdentifier = m_inputHandlerOnImplThread->identifier();
809
810     completion->signal();
811 }
812
813 void CCThreadProxy::initializeContextOnImplThread(CCGraphicsContext* context)
814 {
815     TRACE_EVENT("CCThreadProxy::initializeContextOnImplThread", this, 0);
816     ASSERT(isImplThread());
817     m_contextBeforeInitializationOnImplThread = adoptRef(context);
818 }
819
820 void CCThreadProxy::initializeLayerRendererOnImplThread(CCCompletionEvent* completion, bool* initializeSucceeded, LayerRendererCapabilities* capabilities)
821 {
822     TRACE_EVENT("CCThreadProxy::initializeLayerRendererOnImplThread", this, 0);
823     ASSERT(isImplThread());
824     ASSERT(m_contextBeforeInitializationOnImplThread);
825     *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitializationOnImplThread.release(), textureUploader);
826     if (*initializeSucceeded) {
827         *capabilities = m_layerTreeHostImpl->layerRendererCapabilities();
828         if (capabilities->usingSwapCompleteCallback)
829             m_schedulerOnImplThread->setMaxFramesPending(2);
830     }
831
832     completion->signal();
833 }
834
835 void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completion)
836 {
837     TRACE_EVENT("CCThreadProxy::layerTreeHostClosedOnImplThread", this, 0);
838     ASSERT(isImplThread());
839     m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
840     m_inputHandlerOnImplThread.clear();
841     m_layerTreeHostImpl.clear();
842     m_schedulerOnImplThread.clear();
843     completion->signal();
844 }
845
846 void CCThreadProxy::setFullRootLayerDamageOnImplThread()
847 {
848     ASSERT(isImplThread());
849     m_layerTreeHostImpl->setFullRootLayerDamage();
850 }
851
852 size_t CCThreadProxy::maxPartialTextureUpdates() const
853 {
854     return textureUpdatesPerFrame;
855 }
856
857 void CCThreadProxy::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
858 {
859     ASSERT(isMainThread());
860     CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setFontAtlasOnImplThread, fontAtlas));
861
862 }
863
864 void CCThreadProxy::setFontAtlasOnImplThread(PassOwnPtr<CCFontAtlas> fontAtlas)
865 {
866     ASSERT(isImplThread());
867     m_layerTreeHostImpl->setFontAtlas(fontAtlas);
868 }
869
870 void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, CCGraphicsContext* contextPtr, bool* recreateSucceeded, LayerRendererCapabilities* capabilities)
871 {
872     TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread");
873     ASSERT(isImplThread());
874     m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator());
875     *recreateSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(adoptRef(contextPtr), textureUploader);
876     if (*recreateSucceeded) {
877         *capabilities = m_layerTreeHostImpl->layerRendererCapabilities();
878         m_schedulerOnImplThread->didRecreateContext();
879     }
880     completion->signal();
881 }
882
883 } // namespace WebCore