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